欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的Hibernate框架中的繼承映射學(xué)習(xí)教程

 更新時(shí)間:2016年07月08日 09:59:16   作者:zhang_xinxiu  
Hibernate中的映射可以將類與表對(duì)應(yīng),并利用類的繼承特性,這里我們就來看一下Java的Hibernate框架中的繼承映射學(xué)習(xí)教程

一、繼承映射
繼承是面向?qū)ο蠛苤匾奶匦?,它?shí)現(xiàn)了代碼的服用,在關(guān)系模型中同樣也有繼承關(guān)系,這種繼承關(guān)系其實(shí)可以看做是一種枚舉關(guān)系,一種類型中可以枚舉出很多子類型,這些子類型和父對(duì)象形成了繼承關(guān)系,能夠?qū)ζ溥M(jìn)行枚舉的大部分都可以看做是一種繼承映射,所以這種枚舉關(guān)系可以看做是繼承映射,例如動(dòng)物就是一種抽象類,它是其它動(dòng)物豬、貓等的父類,它們之間就是一種繼承關(guān)系,如下圖:

201678100006100.png (335×264)

這種繼承映射在轉(zhuǎn)化為關(guān)系模型后會(huì)生成一張表,那么這張表是如何區(qū)分這兩種類型的呢?用的是關(guān)系字段,需要在表中添加類型字段,使用關(guān)鍵字來標(biāo)明對(duì)象的類型。所以上圖中的對(duì)象模型對(duì)應(yīng)的表結(jié)構(gòu)如下:

201678100040571.png (669×83)

在生成表結(jié)構(gòu)時(shí),需要添加對(duì)應(yīng)的字段類型,所以需要在映射文件中添加對(duì)應(yīng)的映射鑒別器,這里就需要使用discriminator-value屬性。
1.類文件
類文件中沒有需要注意的地方,在編寫時(shí)注意之間的繼承關(guān)系即可。
清單一:Animal類代碼,只需要添加基本的屬性。

package com.src.hibernate; 
 
public class Animal { 
 
 //id號(hào) 
 private int id; 
 public int getId() { 
 return id; 
 } 
 public void setId(int id) { 
 this.id = id; 
 } 
 
 //名稱 
 private String name; 
 public String getName() { 
 return name; 
 } 
 public void setName(String name) { 
 this.name = name; 
 } 
 
 //性別 
 private boolean sex; 
 public boolean isSex() { 
 return sex; 
 } 
 public void setSex(boolean sex) { 
 this.sex = sex; 
 } 
} 

清單二:Bird和Pig類,添加基本的屬性,并繼承Animal類。

package com.src.hibernate; 
public class Bird extends Animal { 
 
 //高度 
 private int height; 
 public int getHeight() { 
 return height; 
 } 
 public void setHeight(int height) { 
 this.height = height; 
 } 
 
} 
 
package com.src.hibernate; 
public class Pig extends Animal { 
 
 //重量 
 private int weight; 
 public int getWeight() { 
 return weight; 
 } 
 public void setWeight(int weight) { 
 this.weight = weight; 
 } 
} 

2.映射文件
映射文件中需要添加對(duì)應(yīng)的映射,該模型中只需要添加一個(gè)映射文件,因?yàn)橹簧梢粡埍?,在映射文件中添加?duì)應(yīng)的子類映射,使用<subclass>標(biāo)簽,標(biāo)簽中添加鑒別器discriminator-value,該鑒別器屬性指明了在數(shù)據(jù)庫中寫入數(shù)據(jù)時(shí)指示寫入的是何種類型,如下:

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
 <class name="com.src.hibernate.Animal" table="t_animal"> 
 <id name="id"> 
 <generator class="native"/> 
 </id> 
 <!-- 加入鑒別標(biāo)簽,且必須放在id后面 --> 
 <discriminator column="type" /> 
 <property name="name"/> 
 <property name="sex" type="boolean"/> 
 
 <subclass name="com.src.hibernate.Pig" discriminator-value="P"> 
 <property name="weight"/> 
 </subclass> 
 <subclass name="com.src.hibernate.Bird" discriminator-value="B"> 
 <property name="height"/> 
 </subclass> 
 </class> 
 
</hibernate-mapping> 

3.分析結(jié)果
生成的MySQL數(shù)據(jù)庫表中不僅會(huì)添加Animal的基本屬性,而且會(huì)添加Pig和Bird的屬性,因?yàn)樵谟成湮募惺褂?lt;subclass>寫出了所添加的屬性,另外還添加了相應(yīng)的鑒別器屬性,所以在數(shù)據(jù)庫中會(huì)添加對(duì)應(yīng)的鑒別列,生成的表結(jié)構(gòu)如下圖:

201678100102347.png (618×220)

二、數(shù)據(jù)操作

1.寫入數(shù)據(jù)
在進(jìn)行數(shù)據(jù)讀取和寫入操作時(shí)需要注意類中的操作使用了

public void testSave(){ 
 Session session=null; 
 try{ 
 //創(chuàng)建session對(duì)象 
 session=HibernateUtils.getSession(); 
 //開啟事務(wù) 
 session.beginTransaction(); 
 
 Pig pig=new Pig(); 
 pig.setName("小豬豬"); 
 pig.setSex(true); 
 pig.setWeight(200); 
 session.save(pig); 
 
 Bird bird=new Bird(); 
 bird.setName("xiaoniaoniao"); 
 bird.setSex(true); 
 bird.setHeight(100); 
 session.save(bird); 
 
 session.getTransaction().commit(); 
 }catch(Exception e){ 
 e.printStackTrace(); 
 session.getTransaction().rollback(); 
 }finally{ 
 HibernateUtils.closeSession(session); 
 } 
 
} 

2.多態(tài)查詢--get和hql

基本的查詢方法,只需要使用load和get方法即可,這里重點(diǎn)討論多態(tài)查詢。多態(tài)查詢是指Hibernate在加載對(duì)象時(shí)能夠采用instanceof鑒別出其真正的類型的對(duì)象即可為多態(tài)查詢。
Note:多態(tài)查詢不支持延遲加載,也就是說如果使用load方法,需要在映射文件中將延遲加載設(shè)置為false。

3.load延遲加載
load支持延遲加載,在加載對(duì)象時(shí)其實(shí)生成的是對(duì)象的代理,所以在使用多態(tài)查詢時(shí)需要在映射文件中將延遲加載設(shè)置為false,如下:

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
 <class name="com.src.hibernate.Animal" table="t_animal" lazy="false"> 
 <id name="id"> 
 <generator class="native"/> 
 </id> 
 <!-- 加入鑒別標(biāo)簽,且必須放在id后面 --> 
 <discriminator column="type" /> 
 <property name="name"/> 
 <property name="sex" type="boolean"/> 
 
 <subclass name="com.src.hibernate.Pig" discriminator-value="P"> 
 <property name="weight"/> 
 </subclass> 
 <subclass name="com.src.hibernate.Bird" discriminator-value="B"> 
 <property name="height"/> 
 </subclass> 
 </class> 
</hibernate-mapping> 

load加載方法,使用load加載該示例中支持多態(tài)查詢,在配置文件中將延遲加載設(shè)置為false,所以這里使用load方法能夠加載獲得相應(yīng)的對(duì)象類。

public void testLoad(){ 
 Session session=null; 
 try{ 
 session=HibernateUtils.getSession(); 
 session.beginTransaction(); 
 
 Animal ani=(Animal)session.load(Animal.class,1); 
 System.out.println(ani.getName()); 
 //因?yàn)閘oad默認(rèn)支持lazy,所以我們看到的是Animal的代理 
 //所以采用了instanceof無法鑒別出真正的類型Pig 
 //所以load在此情況下是不支持多態(tài)查詢的 
 if(ani instanceof Pig){ 
 System.out.println("我是小豬豬!"); 
 }else{ 
 System.out.println("我不是小豬豬!"); 
 } 
 session.getTransaction().commit(); 
 }catch(Exception e){ 
 e.printStackTrace(); 
 session.getTransaction().rollback(); 
 }finally{ 
 HibernateUtils.closeSession(session); 
 } 
} 

4.hql查詢
hql支持多態(tài)查詢,這主要由于查詢出的是一個(gè)真正的對(duì)象,并不會(huì)返回一個(gè)代理,所以hql支持多態(tài)查詢,另外在查詢時(shí)需要注意查詢語句中不要使用表名,而是要使用類名稱,Hibernate會(huì)根據(jù)類名稱將其映射為對(duì)應(yīng)的表名稱,如下:

public void testLoad5(){ 
 Session session=null; 
 try{ 
 session=HibernateUtils.getSession(); 
 session.beginTransaction(); 
 
 List<Animal> list=session.createQuery("from Animal").list(); 
 for(Iterator iter=list.iterator();iter.hasNext();){ 
 Animal a=(Animal)iter.next(); 
 if(a instanceof Pig){ 
 System.out.println("我是小豬豬!"); 
 }else{ 
 System.out.println("我不是小豬豬!"); 
 } 
 } 
 session.getTransaction().commit(); 
 }catch(Exception e){ 
 e.printStackTrace(); 
 session.getTransaction().rollback(); 
 }finally{ 
 HibernateUtils.closeSession(session); 
 } 
} 

查詢結(jié)果:

Hibernate: select animal0_.id as id0_, animal0_.name as name0_, animal0_.sex as sex0_, animal0_.weight as weight0_, animal0_.height as height0_, animal0_.type as type0_ from t_animal animal0_ 
我是小豬豬! 
我不是小豬豬! 
我是小豬豬! 
我不是小豬豬! 

三、繼承映射三種策略
1. 每個(gè)類分層結(jié)構(gòu)一張表(Table per class hierarchy)

假設(shè)我們有接口Payment和它的幾個(gè)實(shí)現(xiàn)類: CreditCardPayment, CashPayment, 和ChequePayment。則“每個(gè)類分層結(jié)構(gòu)一張表”(Table per class hierarchy)的映射代碼如下所示:

<class name="Payment" table="PAYMENT"> 
 <id name="id" type="long" column="PAYMENT_ID"> 
 <generator class="native"/> 
 </id> 
 <discriminator column="PAYMENT_TYPE" type="string"/> 
 <property name="amount" column="AMOUNT"/> 
 ... 
 <subclass name="CreditCardPayment" discriminator-value="CREDIT"> 
 <property name="creditCardType" column="CCTYPE"/> 
 ... 
 </subclass> 
 <subclass name="CashPayment" discriminator-value="CASH"> 
 ... 
 </subclass> 
 <subclass name="ChequePayment" discriminator-value="CHEQUE"> 
 ... 
 </subclass> 
</class> 

采用這種策略只需要一張表即可。它有一個(gè)很大的限制:要求那些由子類定義的字段, 如CCTYPE,不能有非空(NOT NULL)約束。

2. 每個(gè)子類一張表(Table per subclass)

對(duì)于上例中的幾個(gè)類而言,采用“每個(gè)子類一張表”的映射策略,代碼如下所示:

<class name="Payment" table="PAYMENT"> 
 <id name="id" type="long" column="PAYMENT_ID"> 
 <generator class="native"/> 
 </id> 
 <property name="amount" column="AMOUNT"/> 
 ... 
 <joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT"> 
 <key column="PAYMENT_ID"/> 
 ... 
 </joined-subclass> 
 <joined-subclass name="CashPayment" table="CASH_PAYMENT"> 
 <key column="PAYMENT_ID"/> 
 <property name="creditCardType" column="CCTYPE"/> 
 ... 
 </joined-subclass> 
 <joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT"> 
 <key column="PAYMENT_ID"/> 
 ... 
 </joined-subclass> 
</class> 

需要四張表。三個(gè)子類表通過主鍵關(guān)聯(lián)到超類表(因而關(guān)系模型實(shí)際上是一對(duì)一關(guān)聯(lián))。

3. 每個(gè)子類一張表(Table per subclass),使用辨別標(biāo)志(Discriminator)

注意,對(duì)“每個(gè)子類一張表”的映射策略,Hibernate的實(shí)現(xiàn)不需要辨別字段,而其他 的對(duì)象/關(guān)系映射工具使用了一種不同于Hibernate的實(shí)現(xiàn)方法,該方法要求在超類 表中有一個(gè)類型辨別字段(type discriminator column)。Hibernate采用的方法更 難實(shí)現(xiàn),但從關(guān)系(數(shù)據(jù)庫)這點(diǎn)上來看,按理說它更正確。若你愿意使用帶有辨別字 段的“每個(gè)子類一張表”的策略,你可以結(jié)合使用<subclass> 與<join>,如下所示:

<class name="Payment" table="PAYMENT"> 
 <id name="id" type="long" column="PAYMENT_ID"> 
 <generator class="native"/> 
 </id> 
 <discriminator column="PAYMENT_TYPE" type="string"/> 
 <property name="amount" column="AMOUNT"/> 
 ... 
 <subclass name="CreditCardPayment" discriminator-value="CREDIT"> 
 <join table="CREDIT_PAYMENT"> 
 <property name="creditCardType" column="CCTYPE"/> 
 ... 
 </join> 
 </subclass> 
 <subclass name="CashPayment" discriminator-value="CASH"> 
 <join table="CASH_PAYMENT"> 
 ... 
 </join> 
 </subclass> 
 <subclass name="ChequePayment" discriminator-value="CHEQUE"> 
 <join table="CHEQUE_PAYMENT" fetch="select"> 
 ... 
 </join> 
 </subclass> 
</class> 

可選的聲明fetch="select",是用來告訴Hibernate,在查詢超類時(shí), 不要使用外部連接(outer join)來抓取子類ChequePayment的數(shù)據(jù)。

相關(guān)文章

最新評(píng)論