程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 精通Hibernate之映射繼承關系七

精通Hibernate之映射繼承關系七

編輯:關於JAVA

Company與Employee類之間為一對多多態關聯關系,如果繼承關系樹的根類對應一個表,或者每個類對應一個表,那麼就能映射Company類的employees集合。本節介紹如何映射多對一多態關聯。如圖14-11所示,ClassD與ClassA為多對一多態關聯關系。

假定與ClassD對應的表為TABLE_D,與ClassA對應的表為TABLE_A,在TABLE_D中定義了外鍵A_ID,它參照TABLE_A表的主鍵。

ClassD對象的a屬性既可以引用ClassB對象,也可以引用ClassC對象,例如:

tx = session.beginTransaction();
ClassD d=(ClassD)session.get("ClassD",id);
ClassA a=d.getA();
if(a instanceof ClassB)
System.out.println(((ClassB)a).getB1());
if(a instanceof ClassC)
System.out.println(((ClassC)a).getC1());
tx.commit();

以下代碼在映射ClassD類的a屬性時使用了延遲檢索策略:

<many-to-one name="a"
class="ClassA"
column="A_ID"
lazy="true"
cascade="save-update" />

當Hibernate加載ClassD對象時,它的屬性a引用ClassA的代理類實例,在這種情況下,如果對ClassA的代理類實例進行類型轉換,會拋出ClassCastException:

ClassA a=d.getA();

ClassB b=(ClassB)a; //拋出ClassCastException

解決以上問題的一種辦法是使用Session.load()方法:

ClassA a=d.getA();
ClassB b=(ClassB)session.load(ClassB.class,a.getId());
System.out.println(b.getB1());

當執行Session的load()方法時,Hibernate並不會訪問數據庫,而是僅僅返回ClassB的代理類實例。這種解決辦法的前提條件是必須事先知道ClassD對象實際上和ClassA的哪個子類的對象關聯。

解決以上問題的另一種辦法是顯式使用迫切左外連接檢索策略,避免Hibernate創建ClassA的代理類實例,而是直接創建ClassA的子類的實例:

tx = session.beginTransaction();
ClassD d=(ClassD)session.createCriteria(ClassD.class)
.add(Expression.eq("id",id))
.setFetchMode("a",FetchMode.EAGER)
.uniqueResult();
ClassA a=d.getA();
if(a instanceof ClassB)
System.out.println(((ClassB)a).getB1());
if(a instanceof ClassC)
System.out.println(((ClassC)a).getC1());
tx.commit();

如果繼承關系樹的具體類對應一個表,為了表達ClassD與ClassA的多態關聯,需要在TABLE_D中定義兩個字段:A_ID和A_TYPE,A_TYPE字段表示子類的類型,A_ID參照在子類對應的表中的主鍵。圖14-12顯示了表TABLE_D、TABLE_B和TABLE_C的結構。

圖14-12 表TABLE_D、TABLE_B和TABLE_C的結構

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved