【Hibernate】繼承對映
阿新 • • 發佈:2019-02-02
【前言】
不知道大家是否還記得UML中的四種關係?自己回想了一下,還是沒有忘記的,分別是繼承、實現、依賴和關聯。
怎麼突然會想到這樣一個問題?是因為在學習完Hibernate關聯對映之後,緊接著又來了一個繼承對映。關聯和繼承,都屬於四種關係之一,所以,本篇部落格就先提了個問題,下面就開始繼承對映的學習。
【概述】
繼承是面嚮物件語言的三大重要特性之一,它實現了程式碼的複用。而Hibernate對於此特性在對應的物件模型配置檔案中也作出了各種配置,可將其與關係模型的關係分為三種情況:
1. 每棵類繼承樹一張表
2. 每個類一張表
3. 每個具體類一張表
下面我們就逐一看看,它們各自生成的關係模型有著哪些不同?以下通過動物類和豬類、鳥類三者間的關係為例項,利用不同繼承對映的方法去建表。
三個類之間的關係如下所示:
【一、繼承對映之每棵類繼承樹一張表】
1. 含義:此方法的意思是不管父類擁有多少個子類,都只會根據父類去生成一張表,而各個子類中有單獨的欄位,都新增到父類生成的那張表中。
2. 設計:從圖上看,這張表至少包含的欄位有:id,name,sex,weight和height。但因為子類不止一個,如果沒有一個標識欄位,那麼就無法從資料表中看到記錄是屬於哪個子類的。所以,此張表的結構與資料應該如下:
t_animal:
根據圖建立對應的物件模型,也就是所說的實體類,本篇部落格中實體類程式碼就不再展示了。 3. 配置及註釋:
對於這三種繼承對映方法,目前還沒有在專案中遇到過,所以三者之間如何選擇?通常選擇什麼?都沒有概念。不過總體思想應該仍舊是:沒有最好,選擇合適的就好。也期待在專案中見到對它們的應用。
Id | Name | Sex | Weight | Height | Type |
1 | 小豬豬 | True | 200 | P | |
2 | 小鳥鳥 | False | 100 | B |
4. 結果: 5. 小結: 此種方法的結果就是資料庫中只有一張根據父類建立的表,而不同子類的子屬性也全都寫入到這張表中,增加一個區分欄位即可。 6. 優缺點: (1)表中引入的區分子類的欄位,也就是包括了描述其他欄位的欄位。 (2)如果某個子類的某個屬性不能為空,那麼在資料庫一級不能設定該欄位not null(非空) (3)維護起來方便,只需要修改一個表 (4)靈活性差,表中冗餘欄位會隨著子類的增多而越來越多 【二、繼承對映之每個類一張表】 1. 含義:此種方法的意思是每個類都建立一張單獨的表。 2. 設計:從圖上看,共包含三個類,則應該建立三張表:t_animal、t_pig和t_bird。三張表的結果和資料如下所示: 3. 配置即註釋:<?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 package="com.bjpowernode.hibernate"> <!-- 新建表,名為t_animal。不採用延遲載入 --> <class name="Animal" table="t_animal" lazy="false"> <!-- 該表的主鍵欄位id,生成策略為native --> <id name="id"> <generator class="native"/> </id> <!-- 在父類使用discrimination標籤,用來指定標識欄位的列名和型別 --> <discriminator column="type" type="string"/> <!-- 父類的name屬性 --> <property name="name"/> <!-- 父類的sex屬性 --> <property name="sex"/> <!-- 子類Pig,標識欄位值為P --> <subclass name="Pig" discriminator-value="P"> <!-- 子類Pig的weight屬性 --> <property name="weight"/> </subclass> <!-- 子類Bird,標識欄位值為B --> <subclass name="Bird" discriminator-value="B"> <!-- 子類Bird的height屬性 --> <property name="height"/> </subclass> </class> </hibernate-mapping>
<?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 package="com.bjpowernode.hibernate">
<!-- 建立表t-animal -->
<class name="Animal" table="t_animal">
<!-- 該表的主鍵欄位id,生成策略為native -->
<id name="id">
<generator class="native"/>
</id>
<!-- t_animal的屬性欄位name和sex -->
<property name="name"/>
<property name="sex"/>
<!-- joined-subclass生成策略,新建表t_pig -->
<joined-subclass name="Pig" table="t_pig">
<!-- 指定了pig子類和animal父類之間是通過pid欄位關聯 -->
<key column="pid"/>
<!-- pig子類的子屬性,weight -->
<property name="weight"/>
</joined-subclass>
<!-- joined-subclass生成策略,新建表t_bird -->
<joined-subclass name="Bird" table="t_bird">
<!-- 指定了bird子類和animal父類之間是通過bid欄位關聯 -->
<key column="bid"/>
<!-- bird子類的子屬性,height -->
<property name="height"/>
</joined-subclass>
</class>
</hibernate-mapping>
4. 結果:
5. 小結:
<?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 package="com.bjpowernode.hibernate">
<!-- 定義該表的abstract屬性為true,則不會生成具體的表 -->
<class name="Animal" table="t_animal" abstract="true">
<id name="id">
<!-- 讓應用程式在save()之前為物件分配一個標示符。這是 <generator>元素沒有指定時的預設生成策略。 -->
<generator class="assigned"/>
</id>
<property name="name"/>
<property name="sex"/>
<!-- union-subclass生成策略,t_pig表的資訊是完整的,也就是包含id,name,sex和weight四個欄位 -->
<union-subclass name="Pig" table="t_pig">
<!-- 子屬性欄位weight -->
<property name="weight"/>
</union-subclass>
<!-- union-subclass生成策略,t_bird表的資訊是完整的,也就是包含id,name,sex和height四個欄位 -->
<union-subclass name="Bird" table="t_bird">
<!-- 子屬性欄位height -->
<property name="height"/>
</union-subclass>
</class>
</hibernate-mapping>
4. 結果:
5. 小結:
對於這三種繼承對映方法,目前還沒有在專案中遇到過,所以三者之間如何選擇?通常選擇什麼?都沒有概念。不過總體思想應該仍舊是:沒有最好,選擇合適的就好。也期待在專案中見到對它們的應用。