国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

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

2019-11-26 14:05:11
字體:
供稿:網(wǎng)友

一、繼承映射
繼承是面向?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ù)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 新绛县| 永清县| 北碚区| 浦北县| 荣成市| 牡丹江市| 武宁县| 板桥市| 阳东县| 交口县| 民乐县| 鄂尔多斯市| 宁武县| 调兵山市| 沐川县| 大方县| 瓮安县| 淮阳县| 岳西县| 民勤县| 绥江县| 敦化市| 库尔勒市| 盈江县| 闵行区| 郴州市| 鄯善县| 通化县| 苏尼特右旗| 剑川县| 长武县| 涟水县| 阿城市| 巨鹿县| 鄂尔多斯市| 新绛县| 枣庄市| 西峡县| 北碚区| 上杭县| 柳河县|