1、綜述
你們都知道,hibernate做爲ORM框架的一個具體實現,最大的一個優勢就是是咱們的開發更加的能體現出「面向對象」的思想。在面向對象開發中,類與類之間是能夠相互繼承的(單向繼承),而Hibernate中也對這種繼承關係提供了本身風格的封裝,這就是咱們接下來要介紹的Hibernate繼承映射的三種策略:html
如下UML圖類爲例:java
![](http://static.javashuo.com/static/loading.gif)
一、每棵類繼承樹一張表(能夠理解爲整棵樹一張表,表內有全部字段)web
二、每一個類一張表(父類、子類、子類各一張表,父表中有公共字段,子表中有個性字段+外鍵約束)sql
三、每一個具體類一張表(每一個子類一張表,每張表都有本身全部的屬性字段)app
2、簡介三種繼承映射方式的實現:
實體類也就是咱們的PO對象確定是少不了的,這也是三種方式都必需要有的公共部分了算是:框架
Animal.Java:ssh
- public class Animal {
- private int id;
- private String name;
- private String sex;
-
- public int getId(){
- return id;
- }
- public void setId(int id){
- this.id=id;
- }
- public String getName(){
- return name;
- }
- public void setSex(String name){
- this.name=name;
- }
- public String getSex(){
- return sex;
- }
- public void setSex(String sex){
- this.sex=sex;
- }
- }
Pig.java:oop
- public class Pig extends Animal{
- private int weight;
- public int getWeight(){
- return weight;
- }
- public void setWeight(){
- this.weight=weight;
- }
- }
Bird.java:ui
- public class Bird extends Animal{
- private int height;
- public int getHeight(){
- return height;
- }
- public void setHeight(){
- this.height=height;
- }
- }
3、配置文件分析:
一、每棵類繼承樹一張表(能夠理解爲整棵樹一張表,表內有全部字段)this
Extends.hbm.xml
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal">
- <id name="id">
- <generator class="native"/>
- </id>
- <discriminator column="type" type="string"></discriminator>
- <property name="name"/>
- <property name="sex"/>
- <subclass name="Pig" discriminator-value="Pig">
- <property name="weight"></property>
- </subclass>
- <subclass name="Bird" discriminator-value="Bird">
- <property name="height"></property>
- </subclass>
- </class>
- </hibernate-mapping>
配置映射文件時,父類還用<class>標籤來定義;添加的區分字段(好比上面表1中的Type字段)須要用<discriminator>標籤來定義;用<subclass>標籤訂義兩個子類,與父類「合併」在同一張表裏,子類的特有屬性用<property>屬性定義便可。
映射文件中的子類<subclass>
標籤還能夠與標籤同級,可是要加上屬性extends,屬性值爲父類全路徑名稱。
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal">
- <id name="id">
- <generator class="native"/>
- </id>
- <discriminator column="type" type="string"></discriminator>
- <property name="name"/>
- <property name="sex"/>
- </class>
- <class name="Pig" discriminator-value="Pig" extends="com.ssh.vo.Animal">
- <property name="weight"></property>
- </class>
- <class name="Bird" discriminator-value="Bird" extends="com.ssh.vo.Animal">
- <property name="height"></property>
- </class>
-
- </hibernate-mapping>
![](http://static.javashuo.com/static/loading.gif)
這種映射方式能夠把多個類放在一張表中,可是粒度比較粗,有冗餘字段;但又是由於多個類的相關記錄都存放在一張表中,查詢時不用關聯,所以效率較高。
二、每一個類一張表(父類、子類、子類各一張表,父表中有公共字段,子表中有個性字段+外鍵約束)
Extends.hbm.xml
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <property name="sex"/>
- <joined-subclass name="Pig" table="t_pig">
- <key column="pid" />
- <property name="weight"/>
- </joined-subclass>
- <joined-subclass name="Bird" table="t_bird">
- <key column="bid"/>
- <property name="height"/>
- </joined-subclass>
- </class>
- </hibernate-mapping>
![](http://static.javashuo.com/static/loading.gif)
這種方案相對於上層實現(增刪改查等操做)不變,由於對象模型並無改變,只是關係模型改了,只須要修改映射文件便可。缺點:查詢時須要關聯表,效率差;插入時也要執行多個insert語句,適合繼承程度不深的狀況。優勢:粒度較細,調理清楚,沒有冗餘。
三、每一個具體類一張表(每一個子類一張表,每張表都有本身全部的屬性字段)
Extends.hbm.xml
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal" abstract="true">
- <id name="id">
- <generator class="uuid"/>
- </id>
- <property name="name"/>
- <property name="sex"/>
- <union-subclass name="Pig" table="t_pig">
- <property name="weight"/>
- </union-subclass>
- <union-subclass name="Bird" table="t_bird">
- <property name="height"/>
- </union-subclass>
- </class>
- </hibernate-mapping>
![](http://static.javashuo.com/static/loading.gif)
上面的表有個特色就是,t_pig和t_bird的主鍵永遠都不會相同。由於表面上看起來這是兩張表,但實際上存儲的都是動物(同一類型),因此還能夠看作是一張表。在配置文件中 <union-subclass>標籤中不須要key值了,注意Animal的主鍵生成策略不能是自增(native)了,若是自增的話,pig表中第一條記錄id爲1,bird表中第一條記錄也爲1,而它們在實際意義上屬於同一類型(能夠看作在一張表中),不然可能形成不一樣子類對應表中的主鍵相同,因此主鍵不可一致。配置映射文件時,父類還用<class>標籤來定義;用<union-subclass>標籤訂義兩個子類,且每一個類對應的表的信息是徹底的,包含了全部從父類繼承下來的屬性。子類的特有屬性一樣用<property>定義便可。用abstract屬性表示父類Animal爲抽象類,這樣Animal就不會映射成表了。
4、總結:
若是系統須要常常進行查操做且子類數量較多,則建議用第一種方案,即每棵生成樹映射一張表,這也是最經常使用的方法,效率較高。若是追求細粒度的設計且子類數量很少,則能夠用後兩種方案:每一個類映射一張表或每一個具體類映射一張表。
假如說咱們就是有三張表,分別是T_Animal、T_Pig、T_Bird就是要求咱們用sql語句來完成這些級聯,你們想過sql語句與hbm.xml配置文件的映射關係嗎?其實他就是幫咱們作的表union和表join整合思想,你們能夠思考一下這個問題。