文章出處

當類與類之間建立了關聯,就可以方便的從一個對象導航到另一個對象。或者通過集合導航到一組對象。例如:

對于給定的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-manymany-to-many有效(因為只有這兩種關聯關系包含集合,而one-to-onemany-to-one只含有關系對方的一個引用)。

代碼同理:

說明:如果我既給員工指定了自己所屬的部門,又將員工添加到部門集合中。那么這個時候reverse不設置,生成以下sql

inverse設置為true,不負責維護關聯關系

第二條insert語句已經在員工表中指定了自己所屬的部分,沒有必要再向數據庫發送一條update指令。

將inverse設置成true后,生成的語句如下圖所示。

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()