Java的Hibernate框架中的繼續映照進修教程。本站提示廣大學習愛好者:(Java的Hibernate框架中的繼續映照進修教程)文章只能為提供參考,不一定能成為您想要的結果。以下是Java的Hibernate框架中的繼續映照進修教程正文
1、繼續映照
繼續是面向對象很主要的特征,它完成了代碼的服用,在關系模子中異樣也有繼續關系,這類繼續關系其實可以看作是一種列舉關系,一品種型中可以列舉出許多子類型,這些子類型和父對象構成了繼續關系,可以或許對其停止列舉的年夜部門都可以看作是一種繼續映照,所以這類列舉關系可以看作是繼續映照,例如植物就是一種籠統類,它是其它植物豬、貓等的父類,它們之間就是一種繼續關系,以下圖:
這類繼續映照在轉化為關系模子後會生成一張表,那末這張表是若何辨別這兩品種型的呢?用的是關系字段,須要在表中添加類型字段,應用症結字來標明對象的類型。所以上圖中的對象模子對應的表構造以下:
在生成表構造時,須要添加對應的字段類型,所以須要在映照文件中添加對應的映照辨別器,這裡就須要應用discriminator-value屬性。
1.類文件
類文件中沒有須要留意的處所,在編寫時留意之間的繼續關系便可。
清單一:Animal類代碼,只須要添加根本的屬性。
package com.src.hibernate; public class Animal { //id號 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.映照文件
映照文件中須要添加對應的映照,該模子中只須要添加一個映照文件,由於只生成一張表,在映照文件中添加對應的子類映照,應用<subclass>標簽,標簽中添加辨別器discriminator-value,該辨別器屬性指清楚明了在數據庫中寫入數據時指導寫入的是何品種型,以下:
<?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> <!-- 參加辨別標簽,且必需放在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.剖析成果
生成的MySQL數據庫表中不只會添加Animal的根本屬性,並且會添加Pig和Bird的屬性,由於在映照文件中應用<subclass>寫出了所添加的屬性,別的還添加了響應的辨別器屬性,所以在數據庫中會添加對應的辨別列,生成的表構造以下圖:
2、數據操作
1.寫入數據
在停止數據讀取和寫入操作時須要留意類中的操作應用了
public void testSave(){ Session session=null; try{ //創立session對象 session=HibernateUtils.getSession(); //開啟事務 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.多態查詢--get和hql
根本的查詢辦法,只須要應用load和get辦法便可,這裡重點評論辯論多態查詢。多態查詢是指Hibernate在加載對象時可以或許采取instanceof辨別出其真實的類型的對象便可為多態查詢。
Note:多態查詢不支撐延遲加載,也就是說假如應用load辦法,須要在映照文件中將延遲加載設置為false。
3.load延遲加載
load支撐延遲加載,在加載對象時其實生成的是對象的署理,所以在應用多態查詢時須要在映照文件中將延遲加載設置為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> <!-- 參加辨別標簽,且必需放在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加載該示例中支撐多態查詢,在設置裝備擺設文件中將延遲加載設置為false,所以這裡應用load辦法可以或許加載取得響應的對象類。
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()); //由於load默許支撐lazy,所以我們看到的是Animal的署理 //所以采取了instanceof沒法辨別出真實的類型Pig //所以load在此情形下是不支撐多態查詢的 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支撐多態查詢,這重要因為查詢出的是一個真實的對象,其實不會前往一個署理,所以hql支撐多態查詢,別的在查詢時須要留意查詢語句中不要應用表名,而是要應用類稱號,Hibernate會依據類稱號將其映照為對應的表稱號,以下:
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); } }
查詢成果:
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_ 我是小豬豬! 我不是小豬豬! 我是小豬豬! 我不是小豬豬!
3、繼續映照三種戰略
1. 每一個類分層構造一張表(Table per class hierarchy)
假定我們有接口Payment和它的幾個完成類: CreditCardPayment, CashPayment, 和ChequePayment。則“每一個類分層構造一張表”(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>
采取這類戰略只須要一張表便可。它有一個很年夜的限制:請求那些由子類界說的字段, 如CCTYPE,不克不及有非空(NOT NULL)束縛。
2. 每一個子類一張表(Table per subclass)
關於上例中的幾個類而言,采取“每一個子類一張表”的映照戰略,代碼以下所示:
<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>
須要四張表。三個子類表經由過程主鍵聯系關系到超類表(因此關系模子現實上是一對一聯系關系)。
3. 每一個子類一張表(Table per subclass),應用鑒別標記(Discriminator)
留意,對“每一個子類一張表”的映照戰略,Hibernate的完成不須要鑒別字段,而其他 的對象/關系映照對象應用了一種分歧於Hibernate的完成辦法,該辦法請求在超類 表中有一個類型鑒別字段(type discriminator column)。Hibernate采取的辦法更 難完成,但從關系(數據庫)這點下去看,按理說它更准確。若你情願應用帶有鑒別字 段的“每一個子類一張表”的戰略,你可以聯合應用<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,在查詢超類時, 不要應用內部銜接(outer join)來抓取子類ChequePayment的數據。