Hibernate中的一对多与多对一映射

Posted 十三弦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate中的一对多与多对一映射相关的知识,希望对你有一定的参考价值。

1.需求

  一个部门有多个员工;         【一对多】

  多个员工,属于一个部门    【多对一】

2.实体Bean设计

  Dept:

public class Dept {
    private int depId;
    private String depName;
    private Set<Employee> emps = new HashSet<Employee>();
    set...
    get...      
}

  Employee:

public class Employee {
    private int empId;
    private String empName;
    private double salary;
    private Dept dept;
    set...
    get...
}

3.配置映射文件

  Dept.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.juaner.hibernate.department">
    <class name="Dept" table="t_dept">
        <!--主键-->
        <id name="depId">
            <generator class="native"/>
        </id>
        <property name="depName" column="deptName" type="string"/>
        <!--一对多关联映射的配置-->
        <set name="emps" table="t_employee" >
            <!--外键字段-->
            <key column="dept_id"></key>
            <!--一对多关系-->
            <one-to-many class="Employee"/>
        </set>
    </class>

</hibernate-mapping>

  Employee.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.juaner.hibernate.department">
    <class name="Employee" table="t_employee">
        <!--主键-->
        <id name="empId" column="empId">
            <generator class="native"/>
        </id>
        <property name="empName" column="empName" type="string"/>
        <property name="salary" column="salary"/>
        <!--多对一映射-->
        <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>
    </class>

</hibernate-mapping>

4.保存数据

  • 使用“一”的一方来设置关联
    @Test
    public void test1(){
        Session session = sf.openSession();
        session.beginTransaction();

        //部门对象
        Dept dept = new Dept();
        dept.setDepName("开发部");
        //员工对象
        Employee employee = new Employee();
        employee.setEmpName("张三");
        employee.setSalary(1000);
        Employee employee2 = new Employee();
        employee2.setEmpName("李四");
        employee2.setSalary(2000);

        dept.getEmps().add(employee);
        dept.getEmps().add(employee2);

        session.save(dept);
        session.save(employee);
        session.save(employee2);

        session.getTransaction().commit();
        session.close();
    }

  此时会执行5条sql语句,其中最后两条update语句用来设置关联:

        Hibernate: insert into t_dept (deptName) values (?)
        Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
        Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
        Hibernate: update t_employee set dept_id=? where empId=?
        Hibernate: update t_employee set dept_id=? where empId=?
  • 使用“多”的一方来设置关联
    @Test
    public void test2(){
        Session session = sf.openSession();
        session.beginTransaction();

        //部门对象
        Dept dept = new Dept();
        dept.setDepName("人事部");
        //员工对象
        Employee employee = new Employee();
        employee.setEmpName("张三");
        employee.setSalary(1000);
        Employee employee2 = new Employee();
        employee2.setEmpName("李四");
        employee2.setSalary(2000);

        employee.setDept(dept);
        employee2.setDept(dept);
        //先保存一的一方,再保存多的一方,关系会自动维护,减少不必要的语句
        session.save(dept);
        session.save(employee);
        session.save(employee2);

        session.getTransaction().commit();
        session.close();

    }

  此时只执行三条sql语句:

Hibernate: insert into t_dept (deptName) values (?)
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)

5.inverse属性

  inverse属性用来设置是否控制反转。在一对多的映射中,只能在“一”的一方配置,默认值为false,即“一”的一方掌握控制权。inverse的值对数据的影响如下:

  • 保存数据 有影响

    如果设置控制反转,即inverse=true, 然后通过部门方维护关联关系。在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护。即外键字段为NULL

  • 获取数据 无影响
  • 解除关联关系 有影响

    inverse=false,  可以解除关联

    inverse=true,  当前方没有控制权,不能解除关联关系(不会生成update语句,也不会报错)

  • 删除数据对关联关系 有影响

            inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据

            inverse=true,  没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束!  如果删除的记录没有被引用,可以直接删除

6.cascade属性

  cascade属性用来设置级联方式,它有4个值:

none                 不级联操作, 默认值

save-update     级联保存或更新

delete               级联删除

all                     级联保存、更新、删除

以上是关于Hibernate中的一对多与多对一映射的主要内容,如果未能解决你的问题,请参考以下文章

hibernate关联总结

一对一与多对多与重复条目

hibernate笔记

Hibernate框架--对象的状态,缓存, 映射

--------------Hibernate学习 多对一映射 和 一对多映射

Hibernate的关联关系映射