從字面上翻譯,可以看得出一個table會對應到一個具體類
但是它不像 Table per concrete class with implicit polymorphism 需要一個具體類別就要一個映射檔
Table per concrete class with unions 只需要一個映射檔並透過 union-subclass
來指名具體類是對映到哪個資料表即可
以下以一個"優惠(Preferential)"為一個抽象的父類別,並有兩個子類別
"折扣(Discount)" 以及 "免費(Free)"
首先先來看這三個簡單的Java程式
Preferential.java
package org.pojo; public abstract class Preferential { private int id; //共同屬性 id private String name; //共同屬性 name public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }Discount.java
package org.pojo; public class Discount extends Preferential { private int percent; public int getPercent() { return percent; } public void setPercent(int percent) { this.percent = percent; } }Free.java
package org.pojo; public class Free extends Preferential { private int count; public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
接著是資料表的結構,一個實體類匯對應一個表
Discount.java > t_discount Free.java > t_free
可以看到 id 和 name 都是定義在 Preferential.java裡,因為是共有的
但是你的每個實體資料表則必須都定義的
接著在這種 Table per concrete class with unions 方法中,我們只需要使用一個映射文件檔
Preferential.hbm.xml
<hibernate-mapping>
<!-- abstract 為 true 表示 Preferential 為抽象類別 -->
<class name="org.pojo.Preferential"
abstract="true">
<!-- 共有屬性 -->
<id name="id"
column="id">
<generator class="increment"
/> <!-- 自增 -->
</id>
<!-- 共有屬性 -->
<property name="name"
/>
<!-- 用union-subclass來指名實體纇,及其對應的資料表 -->
<union-subclass name="org.pojo.Discount" table="t_discount">
<!-- 自有的屬性 -->
<property name="percent"
column="percent"/>
</union-subclass>
<union-subclass name="org.pojo.Free"
table="t_free">
<property name="count"
column="count"/>
</union-subclass>
</class>
</hibernate-mapping>
到這邊為止你的繼承工作就完成了,最後別忘了到hibernate.cfg.xml或是hibernate.properties
註冊這個映射檔(Preferential.hbm.xml)
最後來測試一下新增一筆折扣以及一筆免費的過程
以下是JUnit的片段程式
public void testInsert() { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx= session.beginTransaction(); Discount discount = new Discount(); Free free = new Free(); discount.setName("商品A折扣"); discount.setPercent(75); //75折 free.setName("商品A免費"); free.setCount(1); //買一送一 session.save(discount); session.save(free); tx.commit(); session.close(); }如果執行成功你會看到 Hibernate 會下3道SQL,為什麼呢?
Hibernate: select max(ids_.id) from ( select id from t_discount union select id from t_free ) ids_
Hibernate: insert into t_discount (name, percent, id) values (?, ?, ?)
Hibernate: insert into t_free (name, count, id) values (?, ?, ?)
原因是因為兩個資料表的主健都是採用自動遞增的方式,但是id屬性是共通的
它被定義在抽象類別Preferential上,因此Hibernate必須先找出雙方最大的id才能繼續Insert下去
如果今天要找出所有優惠(Preferential)的資料可以如下:
Query query = session.createQuery("from org.pojo.Preferential"); for(Iterator it = query.list().iterator();it.hasNext();){ Preferential preferential = (Preferential)it.next(); System.out.println(preferential.getName()); }
如果想要找出所有折扣(Discount)的資料可以如下:
Query query = session.createQuery("from org.pojo.Discount"); for(Iterator it = query.list().iterator();it.hasNext();){ Discount discount = (Discount)it.next(); System.out.println(discount.getName()); }當然如果想要找出所有的 免費(Free)的資料,就如上依此類推了
沒有留言:
張貼留言