天天看點

Hibernate映射(三)——繼承映射映射1-每棵類繼承樹對應一張表映射2-每個類一張表映射3-每個具體類一張表總結

  當我們的兩個或多個實體類是相似的,或者說他們有很多相同的屬性時,我們通常抽象出父類,子類繼承的方式去實作,以面相對象的特點對實體類進行抽象,封裝和繼承。我們之前學了Hibernate的關系映射,讓我們可以直接面向對象開發,而不是面向資料庫,如何将繼承父類的這種關系反映到資料庫中呢,我們來看Hibernate提供的三種映射政策:

  映射1-每棵類繼承樹對應一張表

  映射2-每個類一張表

  映射3-每個具體類一張表

我們下面以一個簡單的例子說明

首先看我們的類圖

Hibernate映射(三)——繼承映射映射1-每棵類繼承樹對應一張表映射2-每個類一張表映射3-每個具體類一張表總結

  Pig和Bird都繼承自Animal,通過這個簡單的關系來看繼承映射:

映射1-每棵類繼承樹對應一張表

  每棵類繼承樹對應一張表,上面的類圖就是一棵類繼承樹吧,隻映射出一張表,如下:

Hibernate映射(三)——繼承映射映射1-每棵類繼承樹對應一張表映射2-每個類一張表映射3-每個具體類一張表總結

  這是如何做到的,直接看我們的映射檔案:

<hibernate-mapping package="com.bjpowernode.hibernate">
	<class name="Animal" table="t_animal" lazy="false">
		<id name="id">
			<generator class="native"/>
		</id>
		<discriminator column="type" type="string"/>
		<property name="name"/>
		<property name="sex"/>
		<subclass name="Pig" discriminator-value="P">
			<property name="weight"/>
		</subclass>
		<subclass name="Bird" discriminator-value="B">
			<property name="height"/>
		</subclass>
	</class>
</hibernate-mapping>
           

在我們的表中有一個Type字段,他不對應任何一個實體的屬性。Hibernate用這個列自動初始化對應的類并相應進行填充。

<discriminator column="type"type="string"/>,通過discriminator 設定type鑒别字段,在子類中使用discriminator-value屬性辨別每條資料所對應的類。

映射2-每個類一張表

  這種政策是使用joined-subclass标簽來定義子類的。父類、子類,每個類都對應一張資料庫表。

  在父類對應的資料庫表中,實際上會存儲所有的記錄,包括父類和子類的記錄;在子類對應的資料庫表中,這個表隻定義了子類中所特有的屬性映射的字段。子類與父類,通過相同的主鍵值來關聯。如下圖:

Hibernate映射(三)——繼承映射映射1-每棵類繼承樹對應一張表映射2-每個類一張表映射3-每個具體類一張表總結

下面具體的用法:

<hibernate-mapping package="com.bjpowernode.hibernate">
	<class name="Animal" table="t_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>
           

需要注意的:

(1)父類用普通的<class>标簽定義即可

(2)父類不再需要定義discriminator字段

(3)子類用<joined-subclass>标簽定義,在定義joined-subclass的時候,需要注意如下幾點:

   Joined-subclass标簽的name屬性是子類的全路徑名

   Joined-subclass标簽需要包含一個key标簽,這個标簽指定了子類和父類之間是通過哪個字段來關聯的。

此政策特點:

Hibernate每次初始化和填充對象時,會讀取多個表,如果繼承層次多了,性能就會收到影響。

映射3-每個具體類一張表

每個具體類一個表,抽象類沒有表。

這種政策使用union-subclass标簽來定義子類的。每個子類對應一張表,而且這個表包含了所有從父類繼承下來的屬性映射的字段(這就是它跟joined-subclass的不同之處,joined-subclass定義的子類的表,隻包含子類特有屬性映射的字段)。

Hibernate映射(三)——繼承映射映射1-每棵類繼承樹對應一張表映射2-每個類一張表映射3-每個具體類一張表總結

下面具體的用法:

<hibernate-mapping package="com.bjpowernode.hibernate">
	<class name="Animal" table="t_animal" abstract="true">
		<id name="id">
			<generator class="assigned"/>
		</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>
           

需要注意的:

  (1) Union-subclass标簽不再需要包含key标簽(與joined-subclass不同)

  (2) Union-subclass标簽,可以包含在class标簽裡,說明是繼承的class類,也可以不包含在class标簽中,但需要添加extends屬性,值裡是父類的全路徑。

  (3) 此政策,子類會繼承父類的所有屬性,而子類的其它屬性,可以定義在Union-subclass标簽的内部。

總結

  Hibernate 映射政策的三個政策自己的優勢與不足,根據不同的情況去使用,但不管哪種政策,在實作的整個過程中,我們的業務對象與Hibernate持續性架構之間沒有聯系,三個政策完全通過Hibernate的xml配置管理,很展現了Hibernate的靈活性,值得我們學習。