淺析Java的Hibernate框架中的繼承關(guān)系設(shè)計(jì)
這次我們來(lái)說(shuō)一下hibernate的層次設(shè)計(jì),層次設(shè)計(jì)也就是實(shí)體之間的繼承關(guān)系的設(shè)計(jì)。
也許這樣比較抽象,我們直接看例子。
1)我們先看一下普通的做法
直接上代碼:三個(gè)實(shí)類如下:
public class TItem implements Serializable{
//省略Get/Set方法
private int id;
private String manufacture;
private String name;
}
public class TBook extends TItem{
//省略Get/Set方法
private int pageCount;
}
public class TDVD extends TItem{
//省略Get/Set方法
private String regionCode;
}
這里我們需要三個(gè)映射文件,內(nèi)容如下:
<class name="TItem" table="ITEM">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native" />
</id>
<property name="name" column="name" type="java.lang.String"/>
<property name="manufacture" column="manufacture" type="java.lang.String"/>
</class>
<class name="TBook" table="Book">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native" />
</id>
<property name="name" column="name" type="java.lang.String"/>
<property name="manufacture" column="manufacture" type="java.lang.String"/>
<property name="pageCount" column="pageCount" type="java.lang.Integer"/>
</class>
<class name="TDVD" table="DVD">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native" />
</id>
<property name="name" column="name" type="java.lang.String"/>
<property name="manufacture" column="manufacture" type="java.lang.String"/>
<property name="regionCode" column="regionCode" type="java.lang.String"/>
</class>
很普通的映射文件,跟以前的沒(méi)什么區(qū)別。
下面我們直接寫(xiě)一個(gè)測(cè)試方法:
public void testSelect() {
Query query = session.createQuery("from TItem ");
List list = query.list();
Iterator iter = list.iterator();
while(iter.hasNext()) {
System.out.println("Name:"+(((TItem)iter.next()).getName()));
}
}
注意,這里我們是用TItem類,而不是具體的字類,這里它會(huì)自動(dòng)去查找繼承于TItem類的子類,查出所有結(jié)果。這里涉及到一個(gè)多態(tài)模式,class標(biāo)簽有屬性 polymorphism,它的默認(rèn)值為implicit,這意味著不需要指定名稱就可以查詢出結(jié)果。如果為explicit則表明需要指定具體的類名時(shí),才可以查出此類的結(jié)果。
2)上個(gè)例子中我們用到了三個(gè)映射文件,當(dāng)我們需要修改時(shí),就需要修改三個(gè)映射文件,這對(duì)于大的項(xiàng)目是很不可行的。而且每個(gè)表都有對(duì)應(yīng)的主類的對(duì)應(yīng)字段,這是多余的。所以我們有下面這種方法。
實(shí)體類還是跟1)中的一樣。我們把映射文件由三個(gè)改為一個(gè),只保留TItem映射文件。但我們需要做相應(yīng)的修改,現(xiàn)在內(nèi)容如下:
<class name="TItem" table="ITEM" polymorphism="explicit">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native" />
</id>
<property name="name" column="name" type="java.lang.String"/>
<property name="manufacture" column="manufacture" type="java.lang.String"/>
<joined-subclass name="TBook" table="TBOOK">
<key column="id" />
<property name="pageCount" column="pageCount" type="java.lang.Integer" />
</joined-subclass>
<joined-subclass name="TDVD" table="TDVD">
<key column="id"/>
<property name="regionCode" column="regionCode" type="java.lang.String"/>
</joined-subclass>
</class>
這里,我們只有一個(gè)映射文件,但有一個(gè)joined-subclass標(biāo)簽,它表明這個(gè)類繼承于當(dāng)前類,<key>表明分表的主鍵,這里分表是指TBOOK和TDVD這兩個(gè)由子類對(duì)應(yīng)的表。分表中只有字段在property中指定。
這樣當(dāng)我們運(yùn)行后生成的表就如下圖:

兩個(gè)子類對(duì)應(yīng)的表只有我們通過(guò)property指定的字段。這樣就避免了表內(nèi)有多個(gè)字段,使字表只維護(hù)其單獨(dú)字段,當(dāng)item類進(jìn)行改變時(shí),也不用過(guò)多的進(jìn)行修改。
3)再來(lái)了解另外一種方法實(shí)現(xiàn)層次設(shè)計(jì),這就是通過(guò)在表內(nèi)置入標(biāo)志來(lái)實(shí)現(xiàn)。在hibernate的映射文件中我們通過(guò)descriminator標(biāo)簽來(lái)進(jìn)行實(shí)現(xiàn)。
廢話不多說(shuō),我們直接看例子:
我們把昨天的TItem的映射文件修改為:
<class name="TItem" table="ITEM" polymorphism="explicit">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native" />
</id>
<discriminator column="category" type="java.lang.String"/>
<property name="name" column="name" type="java.lang.String"/>
<property name="manufacture" column="manufacture" type="java.lang.String"/>
</class>
看到中間,我們加入了一個(gè)discriminator標(biāo)簽,它表明我們以下的兩個(gè)subclass通過(guò)哪個(gè)字段來(lái)進(jìn)行區(qū)別。
<subclass name="TBook" discriminator-value="1">
<property name="pageCount" column="pageCount"/>
</subclass>
<subclass name="TDVD" discriminator-value="2" >
<property name="regionCode" column="regionCode"/>
</subclass>
我們看到這兩段,它指明了當(dāng)discriminator所指定的field的值為1時(shí),表明它是TBook類,并且pageCount有值;當(dāng)discriminator所指定的field值為2時(shí),表明它是TDVD類,并且regionCode有值。
這樣我們就只需要用到一個(gè)表,就表明了它們幾個(gè)類的關(guān)系了,注意,這種方式對(duì)有過(guò)多子類的情況下,并不好,它會(huì)使主表的字段過(guò)多,會(huì)造成一定的設(shè)計(jì)上的不便。
- Java的Hibernate框架中的繼承映射學(xué)習(xí)教程
- Java的Hibernate框架中復(fù)合主鍵映射的創(chuàng)建和使用教程
- Java的Hibernate框架結(jié)合MySQL的入門學(xué)習(xí)教程
- 深入解析Java的Hibernate框架中的持久對(duì)象
- Java的Hibernate框架中的基本映射用法講解
- Java Hibernate中使用HQL語(yǔ)句進(jìn)行數(shù)據(jù)庫(kù)查詢的要點(diǎn)解析
- Java的Hibernate框架中一對(duì)多的單向和雙向關(guān)聯(lián)映射
- Java的Hibernate框架中的雙向主鍵關(guān)聯(lián)與雙向外鍵關(guān)聯(lián)
- 詳解Java的Hibernate框架中的Interceptor和Collection
- java Hibernate save()與persist()區(qū)別
- 簡(jiǎn)介Java的Hibernate框架中的Session和持久化類
- Java的Hibernate框架中的組合映射學(xué)習(xí)教程
相關(guān)文章
Mybatis查詢數(shù)據(jù)的項(xiàng)目實(shí)現(xiàn)
MyBatis通過(guò)XML配置文件或注解,把Java對(duì)象映射到對(duì)應(yīng)的數(shù)據(jù)庫(kù)表中,實(shí)現(xiàn)對(duì)象關(guān)系和數(shù)據(jù)關(guān)系的互相轉(zhuǎn)換,從而使得Java應(yīng)用程序能夠更簡(jiǎn)單的操作和讀取數(shù)據(jù)庫(kù),本文就詳細(xì)的介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下2023-09-09
跟我學(xué)Java Swing之游戲設(shè)計(jì)(2)
跟我學(xué)Java Swing之游戲設(shè)計(jì)(2)...2006-12-12
springboot基于keytool實(shí)現(xiàn)https的雙向認(rèn)證示例教程
這篇文章主要介紹了springboot基于keytool實(shí)現(xiàn)https的雙向認(rèn)證,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
SpringBoot自定義監(jiān)聽(tīng)器的項(xiàng)目實(shí)踐
Spring Boot提供了強(qiáng)大的事件模型,其中包括多種內(nèi)置監(jiān)聽(tīng)器,同時(shí)也支持開(kāi)發(fā)者自定義監(jiān)聽(tīng)器,下面就來(lái)介紹下SpringBoot自定義監(jiān)聽(tīng)器,感興趣的可以了解一下2024-03-03
如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能
人工智能時(shí)代的到來(lái),相信大家已耳濡目染,虹軟免費(fèi),離線開(kāi)放的人臉識(shí)別SDK,正推動(dòng)著全行業(yè)進(jìn)入刷臉時(shí)代,下面這篇文章主要給大家介紹了關(guān)于如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能的相關(guān)資料,需要的朋友可以參考下2022-05-05

