Hibernate 作為ORM,面對(duì)的一個(gè)問題是:一個(gè)方面是關(guān)系型的數(shù)據(jù)庫(kù),另一面是Java Object。Java作為一種面向?qū)ο蟮恼Z(yǔ)言支持繼承關(guān)系。Hibernate本身提供了4種策略將繼承關(guān)系映射到關(guān)系型的數(shù)據(jù)庫(kù)中。他們分別是:
?
- Table Per Concrete Class with Implicit Polymorphism : 每個(gè)Concrete Class 對(duì)應(yīng)一張Table。利用Hibernate內(nèi)部的機(jī)制來(lái)實(shí)現(xiàn)多態(tài)型的查詢。對(duì)于SuperClass Query是分成對(duì)Concrete Class的獨(dú)立Query組合起來(lái)的。
- Table Per Concrete Class with Union : 每個(gè)Concrete Class 對(duì)應(yīng)一張Table。對(duì)于SuperClass Query是通過Union的方式來(lái)實(shí)現(xiàn)的。
- Table Per Class Hierarchy : 將整個(gè)Class Hierachy的關(guān)系Mapping到一張Table中,通過discriminator來(lái)區(qū)分具體的Concrete Class。
- Table Per SubClass:對(duì)于Class Hierachy圖中的每個(gè)類都對(duì)應(yīng)有一張Table。
這些策略各有特點(diǎn),應(yīng)用場(chǎng)合不同。在具體實(shí)現(xiàn)的時(shí)候,應(yīng)該仔細(xì)選擇。
?
一、例子的背景:
?
?假如我們有如下的類的關(guān)系,需要將他們mapping到數(shù)據(jù)庫(kù)中
?
??每個(gè)類的代碼如下:
package org.example.hibernate.domain; //BillDetail SuperClass public class BillingDetail { private Long id; private String owner; //省略相應(yīng)的get/set accessor }
?
package org.example.hibernate.domain; //Concrete Class BankAccount public class BankAccount extends BillingDetail{ private String account; private String bankName; private String swift; //省略相應(yīng)的get/set accessor }
?
package org.example.hibernate.domain; //Concrete Class CreditCard public class CreditCard extends BillingDetail { private String number; private String expMonth; private String expYear; //省略相應(yīng)的get/set accessor }
?
二、使用T/CCIP(Table Per Concrete Class with Implicit Polymorphism)策略來(lái)映射
1. 只對(duì)Concrete Class建立Table,SuperClass中的property,直接mapping到Concrete Class相應(yīng)Table的column
2. 對(duì)于Concrete Class的mapping,就如同沒有SuperClass的普通Class一樣mapping。
?
?? Mapping File如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- CreditCard Class Mapping Section--> <class name="org.example.hibernate.domain.CreditCard" table="CREDITCARD" polymorphism="implicit"> <id name="id" column="IDNUM" type="long"> <generator class="native"/> </id> <property name="owner" type="string" column="OWNER" length="30"/> <property name="number" type="string" column="NUMBER_CODE" length="20"/> <property name="expMonth" type="string" column="EXP_MONTH" length="2"/> <property name="expYear" type="string" column="EXP_YEAR" length="4"/> </class> <!-- BankAccount Class Mapping Section--> <class name="org.example.hibernate.domain.BankAccount" table="BANK_ACCOUNT" polymorphism="implicit"> <id name="id" column="IDNUM" type="long"> <generator class="native"/> </id> <property name="owner" type="string" column="OWNER" length="30"/> <property name="account" type="string" column="ACCOUNT" length="20"/> <property name="bankName" type="string" column="BANK_NAME" length="255"/> <property name="swift" type="string" column="SWIFT" length="3"/> </class> </hibernate-mapping>
?
如Mapping File中看到的,CreditCard和BankAccount的Id都是采用Hibernate的native策略。當(dāng)Session對(duì)CreditCard和BankAccount的instance做save的時(shí)候,insert到相應(yīng)table中的idnum欄位的value可能是一樣的。因?yàn)樗麄兊腍ibernate Id 產(chǎn)生策略獨(dú)立的,彼此沒有任何的關(guān)系。?
//Transaction Commit以后,cc11的Id Value是1 CreditCard cc11 = new CreditCard(); cc11.setOwner("jessecia"); cc11.setNumber("123123123123123"); session.save(cc11); //Transaction Commit以后,ba11的Id Value是1 BankAccount ba11 = new BankAccount(); ba11.setOwner("jessecia"); ba11.setBankName("GBDFB"); session.save(ba11);
?
??? 而對(duì)于BillingDetail的polymorphic query,則分成2個(gè)獨(dú)立的對(duì)CreditCard和BankAccount表的查詢SQL來(lái)獲得。Java代碼如下:
Criteria criteria = session.createCriteria(BillingDetail.class); List<BillingDetail> list = criteria.list();
???
?? 產(chǎn)生的SQL如下:?
select this_.IDNUM as IDNUM0_0_ , this_.NUMBER_CODE as NUMBER2_0_0_ , this_.EXP_MONTH as EXP3_0_0_ , this_.EXP_YEAR as EXP4_0_0_ , this_.OWNER as OWNER0_0_ from CREDITCARD this_ select this_.IDNUM as IDNUM1_0_ , this_.ACCOUNT as ACCOUNT1_0_ , this_.BANK_NAME as BANK3_1_0_ , this_.SWIFT as SWIFT1_0_ , this_.OWNER as OWNER1_0_ from BANK_ACCOUNT1 this_
?
? T/CCIP方式的結(jié)論:
1.??應(yīng)用場(chǎng)合:不適合于Polymorphic Association的應(yīng)用場(chǎng)合。也就是說(shuō)SupperClass和其他的Persistent Class發(fā)生關(guān)系。
2.? 擴(kuò)展性:當(dāng)SuperClass增加新的Property的時(shí)候,每個(gè)Concrete Class相應(yīng)的Table都需要新增Column
?
?下一篇:Class Hierachy的映射策略之T/CCU
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
