美文网首页
java框架Hibernate的一对多与多对一映射

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

作者: _琳哥 | 来源:发表于2017-11-21 21:17 被阅读92次

    一对多与多对一映射实现步骤
    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 同上。级联保存、更新、删除

    相关文章

      网友评论

          本文标题:java框架Hibernate的一对多与多对一映射

          本文链接:https://www.haomeiwen.com/subject/hdqbvxtx.html