hibernate的3种继承映射关系总结——TPH,TPS,TPC
Java類中有繼承關系,相應的在hibernate中,也有繼承關系,子類反應到數據庫中,就有多種實現形式了,子類和父類可以映射到同一張表中,子類也可以單獨映射成一張表,但是用不同的標簽實現,子類表和父類表的關系也不同。
下面對以前做的project進行總結一下
為了將程序領域中的繼承關系反映到數據 中,Hibernate為我們提供了3中方案:
第一種方案:每棵類繼承樹一張表(Table Per Hierarchy)TPH
第二種方案:每個子類一張表(Table Per Subclass)TPS
第三種方案:每個具體的類一張表(Table Per Concrete class)TPC
就下圖的繼承關系來闡明三種方法:
對應的三個PO:
Person.java
package com.hust.PO;public class Person {private Integer id; private String name; //姓名private Integer age; //年齡private String sex; //性別//省略getter和setter函數 } Student.java
package com.hust.PO;public class Student extends Person {//private Integer sid; //TPS每個子類一張表時,要新增這個屬性,學生標識,與父類person內連接private String sno; //學號private String school; //學校//省略getter和setter函數 } Worker.java
package com.hust.PO;public class Worker extends Person {//private Integer wid; //TPS每個子類一張表時,增加這個屬性,工人標識,與父類person內連接private String wno; //工號private Double salary; //工資//省略getter和setter函數 } 一.每棵類繼承樹一張表(Table Per Hierarchy)TPH
? ?http://blog.csdn.net/tuke_tuke/article/details/49981013
? ? ?所謂一棵繼承樹一張表,就是子類屬性和父類屬性放在一張表中,但是要指定鑒別器列,用subclass一定要有判斷類型的一個列,鑒別器指定記錄屬于哪個類型
person表
只有一個父類person表,只有一個映射文件Person.hbm.xml
Person.hbm.xml
<?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 package="com.hust.PO"><!-- 一個繼承樹一張表 --> <!-- 父類 --> <class name="Person" table="person"> <id column="id" name="Id" type="integer"> <!-- 主鍵生成策略為 '分配' --> <generator class="assigned"></generator> </id> <!-- 鑒定列,區分列 discriminator 鑒別器--> <discriminator column="Type" type="string"></discriminator><property column="Name" name="name" type="string"></property> <property column="Age" name="age" type="integer"></property> <property column="Sex" name="sex" type="string"></property> <!-- 子類,其鑒定列值為'stu' name是PO類名--> <subclass name="Student" discriminator-value="stu"> <property column="School" name="school" type="string"></property> <property column="Sno" name="sno" type="string"></property> </subclass> <!-- 子類,其鑒定列值為'worker' name是PO類名--> <subclass name="Worker" discriminator-value="worker"> <property column="Wno" name="wno" type="string"></property> <property column="Salary" name="salary" type="double"></property> </subclass> </class> </hibernate-mapping> 所謂的將整個繼承樹映射到同一個表當中,即子類的信息,全部映射到了父類對應的表中。 <discriminator>標簽用于在表中創建一個標識列,其"column"屬性指定標識列的列名,"type"指定了標識列的類型。注意, 一定要指定鑒別器,它的作用是在父類的映射表中,添加了一個type的列,用來鑒別員工是屬于哪個子類,并且在每個類的標簽中要指定鑒別器值。
結果:
二,每個子類一張表(Table Per Subclass)TPS
??http://blog.csdn.net/tuke_tuke/article/details/50082457
??所謂“每個子類一張表”:父類一張表,每個子類一張表,父類的表保存公共有信息,子類的表只保存自己特有的信息
三個表的關系:
person表
student表
worker表
只有一個父類映射文件Person.hbm.xml,三張表
Person.hbm.xml
<?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.hust.PO"> <!-- Person表 --> <class name="Person" table="person"> <!-- person 表保存公共屬性 --><id name="id"> <!-- 父類的主鍵生成策略為‘分配’ --> <generator class="assigned"></generator> </id> <property name="name" column="Name" type="string"></property> <property name="sex" column="Sex" type="string"></property> <property name="age" column="Age" type="java.lang.Integer"></property> <!-- student表 ,name是類名。table是對應的表名--> <joined-subclass name="Student" table="student"> <key column="Sid"></key> <!-- 指定了子類和父類之間是通過哪個字段來關聯的 ,這里的關聯是內連接--><property column="Sno" name="sno" type="string" ></property> <!-- 子類特征屬性 --><property column="School" name="school" type="string" ></property> <!-- 子類特征屬性 --></joined-subclass> <!-- worker表 --> <joined-subclass name="Worker" table="worker"> <key column="Wid"></key> <property column="Wno" name="wno" type="string" ></property> <!-- 子類特征屬性 --><property column="Salary" name="salary" type="double" ></property> <!-- 子類特征屬性 --></joined-subclass> </class> </hibernate-mapping> <joined-subclass>標簽需要包含一個key標簽,這個標簽指定了子類和父類之間是通過哪個字段來關聯的。
根據People.hbm.xml生成表結構, 可以看到,父類對應的表保存公有信息,子類對應的表保存獨有信息,子類和父類對應的表使用一對一主鍵關聯的方式關聯起來
用joined-subclass只能創建為子類單獨創建表,子類對應的表的主鍵和外鍵都是其父類的主鍵。注意,joined-subclass不能和subclass混合使用
結果:
person表結果 ? ? ? ? ? ? ? ? ? ? ? ? student表結果 ? ? ? ? ? ? ? ? ? ? ? ? ? ? worker表結果
? ? ??? ? ?
三,每個具體的類一張表(Table Per Concrete class)TPC
? ?http://blog.csdn.net/tuke_tuke/article/details/50085449 ? ??
所謂是“每個具體類一張表(table per concrete class)”的意思是:使繼承體系中每一個子類都對應數據庫中的一張表。每一個子類對應的數據庫表都包含了父類的信息,并且包含了自己獨有的屬性。每個子類對應一張表,而且這個表的信息是完備的,即包含了所有從父類繼承下來的屬性映射的字段
只有兩個表的關系:
student表
worker表
注意:只要一個父類映射表Person.hbm.xml,兩張表
Person.hbm.xml
<?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.hust.PO"> <!-- table per concrete(TPC) (a. 具體的,實際的) --> <!-- 每一個具體類一張表 --> <!-- 虛擬選項為'true' --> <class name="Person" table="person" abstract="true"> <!-- 多設置一個屬性abstract="true",因為根本就沒有person表 --><id column="Id" name="id" type="integer"> <!-- 主鍵的生成策略為'分配' --> <generator class="assigned"></generator> </id> <property column="Name" name="name" type="string"></property> <property column="Sex" name="sex" type="string"></property> <property column="Age" name="age" type="integer"></property> <!-- 公共屬性 --><!--student具體類--> <union-subclass name="Student" table="student"> <property column="Sno" name="sno" type="string"></property> <!-- 特征屬性 --> <property column="School" name="school" type="string"></property> <!-- 特征屬性 --></union-subclass> <!--worker具體類--> <union-subclass name="Worker" table="worker"> <property column="Wno" name="wno" type="string"></property> <!-- 特征屬性 --><property column="Salary" name="salary" type="double"></property> <!-- 特征屬性 --></union-subclass> </class> </hibernate-mapping> <class>標簽中的"abstract"屬性如果值為true則,不會生成表結構。如果值為false則會生成表結構( 貌似是根據映射文件生成表結構,不是很理解),但是不會插入數據。
把父類設為抽象的類,并且在映射文件中,把父類設置為abstract="true",那么就不會再數據庫中生成父類對應的表了,父類就只起到一個抽象的作用了。
union-subclass是將父類中的屬性,添加到子類對應的表中去了.
結果:
student表
worker表
三種方式的優缺點:
1,首先表中引入的區分子類的字段,也就是包括了描述其他字段的字段。其次,如果某個子類的某個屬性不能為空,那么在數據庫一級不能設置該字段not null(非空),維護起來方便,只需要修改一個表,靈活性差,表中冗余字段會隨著子類的增多而越來越多。在任何情況下,都只需處理一個表,對于單個對象的持久話操作只需要處理一個表
2,這種設計方式完全符合關系模型的設計原則,且不存在冗余,維護起來比較方便,對每個類的修改只需要修改其所對應的表,靈活性很好,完全是參照對象繼承的方式進行配置,對于父類的查詢需要使用左外鏈接,對于子類查詢需要使用內鏈接,對于子類的持久話至少要處理兩個表
3,這種設計方式符合關系模型的設計原則,但有表中存在重復字段的問題。如果需要對基類進行修改,則需要對基類以及該類的子類所對應的所有表都進行修改,映射的靈活性很大,子類可以包括基類屬性在內的每一個屬性進行單獨配置,對于子類的查詢只需要訪問單獨的表,對父類查詢怎需要檢索所有的表,對于單個對象持久話操作只需要處理一個表
總結
以上是生活随笔為你收集整理的hibernate的3种继承映射关系总结——TPH,TPS,TPC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hibernate继承关系映射方法(三)
- 下一篇: 链表用java实现简单单链表linked