zoukankan      html  css  js  c++  java
  • 映射一对多双向关联关系 cascade、inverse、属性

    当类与类之间建立了关联,就可以方便的从一个对象导航到另一个对象。或者通过集合导航到一组对象。例如:

    对于给定的Emp对象,如果想获得与它关联的Dept对象,只要调用如下方法

    Dept dept=emp.getDept(); //从Emp对象导航到关联的Dept对象 

    以Dept(部门)类和Emp(员工)类为例:

    一、配置双向一对多关联

    需在Dept类中增加一个集合类型的emps属性

    复制代码
    复制代码
    复制代码
        private Set<Emp> emps=new HashSet<Emp>();
    
        public Set<Emp> getEmps() {
        return emps;
    }
    
        public void setEmps(Set<Emp> emps) {
        this.emps = emps;
    复制代码
    复制代码
    复制代码

    如何在映射文件中映射集合类型的emps属性。由于在Dept表中没有直接与emps属性对应的字段。因此不能用<property>元素来映射emps属性,而要使用<set>元素:

     <set name="emps">
            <key column="deptNo"></key>  <!-- 多的一方 emp外键 -->
            <one-to-many class="Emp" />
          </set>

    解析:

    <set>元素的name属性:设定持久化类的属性名。此处为Dept类的emps属性。

    <set>元素还包含两个子元素:

    ①<key>元素:column属性设定与所关联的持久化类对应的表的外键

    ②<one-to-many>元素:class属性设定与所关联的持久化类

    hibernate根据以上映射代码获得以下信息:

    ①<set>元素表明Dept类的emps属性为java.util.Set集合类型

    ②<one-to-many>子元素表明emps集合中存放的是一组Emp对象

    ③<key>子元素表明EMP表通过外键DEPTNO参照Dept表

    Dept.hbm.xml代码:

    复制代码
    复制代码
    复制代码
    <?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="cn.happy.onetomanydouble">
       <class name="Dept" table="DEPT">
          <id name="deptNo">
            <generator class="sequence">
              <param name="sequence">SEQ_NUM</param>
            </generator>
          </id> 
          <property name="deptName"/>
          
          <!-- 一对多一个配置,一个部门有N个员工 -->
          <!--
             inverse="false"  主动方   维护关联关系
             
              inverse="true"  不维护关联关系(不干扰Emp的外键生成)
           -->
          <set name="emps" cascade="save-update">
            <key column="deptNo"></key>  <!-- 多的一方 emp外键 -->
            <one-to-many class="Emp" />
          </set>
          
       </class>
    </hibernate-mapping>
    复制代码
    复制代码
    复制代码

    Emp.hbm.xml:

    复制代码
    复制代码
    复制代码
    <?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="cn.happy.onetomanydouble">
       <class name="Emp" table="EMP">
          <id name="empId">
            <generator class="sequence">
              <param name="sequence">SEQ_NUM</param>
            </generator>
          </id> 
          <property name="empName" type="string"/>
          
          <!-- 植入一个Dept对象 : 多对一-->
          <many-to-one name="dept" class="Dept" column="deptNo"></many-to-one>
       </class>
    </hibernate-mapping>
    复制代码
    复制代码
    复制代码

    进而编写测试类:Test 即可拿到deptNo为1的员工姓名

    复制代码
    复制代码
    复制代码
    public class Test2 {
    
        Session session;
        Transaction tx; 
    
        @After
        public void afterTest(){
            tx.commit();
            HibernateUtil.CloseSession();
        }
    
        @Before
        public void initData(){
            session=HibernateUtil.getSession();
            tx=session.beginTransaction();
        }
        
        /*
         * 一对多双向关联测试
         */
        @Test
        public void oneToManyDoubleTest(){
    
            //获取员工集合
            Dept dept=(Dept)session.load(Dept.class,1);
             Set<Emp> emps =dept.getEmps();
            for (Emp emp : emps) {
                System.out.println(emp.getEmpName());
            }
        }
    复制代码
    复制代码
    复制代码

    二、cascade属性

     none:当Session操纵当前对象时,忽略其他关联的对象。它是cascade属性的默认值.

     Save-update:当通过Session的save()、update()及saveOrUpdate()方法来保存或更新当前对象时,级联保存所有关联的新建的瞬时状态的对象,并且级联更新所有关联的游离状态的对象。

     Delete:当通过Session的delete()方法删除当前对象时,会级联删除所有关联的对象。

    当通过Session的delete()方法删除当前对象时,会级联删除所有关联的对象。

     All:包含save-update,delete的行为。

    解析:

    级联也就是说当我们保存持久化对象A的时候自动帮我们保存持久化对象B。

    问题:cascade属性写在什么位置?

    注:一对一或者多对一的时候,直接写在标签上,其他的写在set标签上。

    如何实现添加部门的同时自动添加员工?

    解析:可以使用cascade(级联)方式

    Test:双向关联  通过add()将新建的员工对象添加部门下

    复制代码
    复制代码
    复制代码
    public class Test3 {
        
        Session session;
        Transaction tx; 
    
        @After
        public void afterTest(){
            tx.commit();
            HibernateUtil.CloseSession();
        }
    
        @Before
        public void initData(){
            session=HibernateUtil.getSession();
            tx=session.beginTransaction();
        }
        
        /*
         *cascade
         */
        @Test
        public void oneTest(){
        
            
            //构建一个部门
            Dept dept=new Dept();
            dept.setDeptName("财务部");
            
            //构建一个员工
            Emp emp=new Emp();
            emp.setEmpName("张三");
            
            //指定员工隶属的部门
            emp.setDept(dept);
            
    
            // setXXX 部门下的员工
            dept.getEmps().add(emp);
            
            //save
            
            session.save(dept);
            session.save(emp);
        }
        
        }
    复制代码
    复制代码
    复制代码

    三、<Set>元素下的inverse属性(反转)

    inverse属性指定了关联关系中的方向。

    inverse设置为false,则为主动方,由主动方负责维护关联关系,默认是false 。

    注意:inverse 决定是否把对对象中集合的改动反映到数据库中,所以inverse只对集合起作用,也就是只对one-to-many或many-to-many有效(因为只有这两种关联关系包含集合,而one-to-one和many-to-one只含有关系对方的一个引用)。

    代码同理:

    说明:如果我既给员工指定了自己所属的部门,又将员工添加到部门集合中。那么这个时候reverse不设置,生成以下sql

    inverse设置为true,不负责维护关联关系

    第二条insert语句已经在员工表中指定了自己所属的部分,没有必要再向数据库发送一条update指令。

    将inverse设置成true后,生成的语句如下图所示。

  • 相关阅读:
    Atitit.Java exe bat  作为windows系统服务程序运行
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结
  • 原文地址:https://www.cnblogs.com/6zhi/p/5833875.html
Copyright © 2011-2022 走看看