java框架Hibernate的一对多与多对一映射


一对多与多对一映射实现步骤
javaBean类
  • 部门类
public class Dept {

    private int deptId;
    private String deptName;
    private Set<Employee> emps;

    public int getDeptId(){
        return deptId;
    }

    public void setDeptId(int deptId){
        this.deptId = deptId;
    }

    public String getDeptName(){
        return deptName;
    }

    public void setDeptName(String deptName){
        this.deptName = deptName;
    }

    public Set<Employee> getEmps(){
        return emps;
    }

    public void setEmps(Set<Employee> emps){
        this.emps = emps;
    }
}
  • 员工类
public class Employee {

    private int empId;
    private String empName;
    private double salary;
    // [多对一]员工与部门
    private Dept dept;

    public int getEmpId(){
        return empId;
    }

    public void setEmpId(int empId){
        this.empId = empId;
    }

    public String getEmpName(){
        return empName;
    }

    public void setEmpName(String empName){
        this.empName = empName;
    }

    public double getSalary(){
        return salary;
    }

    public void setSalary(double salary){
        this.salary = salary;
    }

    public Dept getDept(){
        return dept;
    }

    public void setDept(Dept dept){
        this.dept = dept;
    }
}
配置文件设置
  • 部门的配置文件
<?xml version="1.0"?>
<!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.flynn.one2many">
    <class name="Dept" table="t_dept">

        <id name="deptId">
            <generator class="native"/>
        </id>
        <property name="deptName"></property>

        <!--
            一对多关联映射的配置(通过部门管理到员工)
            Dept 映射关键点:
                1.  指定 映射的集合属性: "emps"
                2.  集合属性对应的集合表: "t_employee"
                3.  集合表的外键字段   "t_employee. dept_id"
                4.  集合元素的类型
        -->
        <set name="emps" table="t_employee">
            <key column="dept_id"></key>
            <one-to-many class="Employee"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
  • 员工的配置文件
<?xml version="1.0"?>
<!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.flynn.one2many">
    <class name="Employee" table="t_employee">

        <id name="empId">
            <generator class="native"/>
        </id>
        <property name="empName" length="20"></property>
        <property name="salary" type="double"></property>

        <!--
            多对一映射配置
            Employee 映射关键点:
                1.  映射的部门属性  :  dept
                2.  映射的部门对象,对应的外键字段: dept_id
                3.  部门的类型
        -->
        <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>

    </class>
</hibernate-mapping>
测试
    @Test
    public void testSaveDept(){
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("app developer");
        // 员工对象
        com.flynn.one2many.Employee emp_zs = new com.flynn.one2many.Employee();
        emp_zs.setEmpName("zhangsan");
        com.flynn.one2many.Employee emp_ls = new com.flynn.one2many.Employee();
        emp_ls.setEmpName("lishi");
        // 关系
        Set<com.flynn.one2many.Employee> set = new HashSet<>();
        set.add(emp_zs);
        set.add(emp_ls);
        dept.setEmps(set);
        // 保存
        session.save(emp_zs);
        session.save(emp_ls);
        session.save(dept); // 保存部门 部门下所有的员工

        session.getTransaction().commit();
        session.close();
        /*
            控制台Hibernate的打印:
            Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
            Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
            Hibernate: insert into t_dept (deptName) values (?)
            Hibernate: update t_employee set deptId=? where empId=?
            Hibernate: update t_employee set deptId=? where empId=?
         */
    }

// [推荐] 保存, 部员方[多的一方操作]
    @Test
    public void testSaveEmp(){
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("java developer");
        // 员工对象
        com.flynn.one2many.Employee emp_zs = new com.flynn.one2many.Employee();
        emp_zs.setEmpName("zhangsan");
        com.flynn.one2many.Employee emp_ls = new com.flynn.one2many.Employee();
        emp_ls.setEmpName("lishi");
        // 关系
        emp_zs.setDept(dept);
        emp_ls.setDept(dept);
        // 保存
        session.save(dept);  // 先保存一的方法
        session.save(emp_zs);
        session.save(emp_ls); // 再保存多的一方, 关系会自动维护(映射配置完)

        session.getTransaction().commit();
        session.close();
        /*
            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 (?, ?, ?)
         */
    }


    /**
     * 获取数据
     */
    @Test
    public void testDeptOrEmp(){
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        // 1.通过部门方, 获取另外一方
        Dept dept = (Dept) session.get(Dept.class, 1);
        System.out.println(dept.getDeptName());
        System.out.println(dept.getEmps()); // 懒加载

        // 2.通过员工方, 获取另外一方
        com.flynn.one2many.Employee employee = (com.flynn.one2many.Employee) session.get(com.flynn.one2many.Employee.class, 1);
        System.out.println(employee.getEmpName());
        System.out.println(employee.getDept());
    }

在一对多与多对一的关联关系中, 保存数据最好的通过多的一方来维护关系, 这样可以减少update语句的生成, 从而提高 hibernate 的执行效率 !

配置一对多与多对一 , 这种叫"双向关联"
只配置一对多 , 叫"单项一对多"
只配置多对一, 叫"单项多对一"

注意:

  • 配置了哪一方, 哪一方才有维护关联关系的权限!

Inverse属性

Inverse属性,是在维护关联关系的时候起作用的。
表示控制权是否转移。(在一的一方起作用)

Inverse , 控制反转。
Inverse = false 不反转; 当前方有控制权
True 控制反转; 当前方没有控制权

维护关联关系中,是否设置inverse属性:

    1. 保存数据
      有影响。
      如果设置控制反转,即inverse=true, 然后通过部门方维护关联关系。在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护。即外键字段为NULL
      image.png
    1. 获取数据
      无。
    1. 解除关联关系?
      有影响。
    • inverse=false, 可以解除关联
    • inverse=true, 当前方(部门)没有控制权,不能解除关联关系 (不会生成update语句,也不会报错)
    1. 删除数据对关联关系的影响?
      有影响。
    • inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。
    • inverse=true, 没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束! 如果删除的记录没有被引用,可以直接删除。
cascade 属性

cascade 表示级联操作 【可以设置到一的一方或多的一方】

  • none 不级联操作, 默认值
  • save-update 级联保存或更新
  • delete 级联删除
  • save-update,delete 级联保存、更新、删除
  • all 同上。级联保存、更新、删除
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容