在上一篇《Eclipse 快速上手 Hibernate:繼承映射 (1)》中,我們詳細探討了「每個類層次結構一張表」的策略。本文將繼續深入,介紹另一種常見的繼承映射策略——「每個子類一張表」。為避免重複,專案建立與基礎配置等共通部分請參考前文。
沿用現有的 InheritanceMapping Java 專案。在包 javamxj.inheritance.two 下建立以下類別:
父類別僅包含基本屬性 id 和 name,對應資料庫中的主表。
package javamxj.inheritance.two;
/**
* @hibernate.class
*/
public class Vehicle {
private Long id;
private String name;
/** @hibernate.id column="ID" generator-class="hilo" unsaved-value="null" */
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
/** @hibernate.property length="24" */
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
關鍵在於使用 @hibernate.joined-subclass 標記,並指定連接鍵欄位。
package javamxj.inheritance.two;
/**
* @hibernate.joined-subclass
* @hibernate.joined-subclass-key column="id"
*/
public class Car extends Vehicle {
private String seat;
/** @hibernate.property column="載客" length="24" */
public String getSeat() { return seat; }
public void setSeat(String seat) { this.seat = seat; }
}
package javamxj.inheritance.two;
/**
* @hibernate.joined-subclass
* @hibernate.joined-subclass-key column="id"
*/
public class Truck extends Vehicle {
private String load;
/** @hibernate.property column="載重" length="24" */
public String getLoad() { return load; }
public void setLoad(String load) { this.load = load; }
}
執行 Ant 任務 generate-hbm,Eclipse 會自動生成 Vehicle.hbm.xml。核心部分為 <joined-subclass> 標籤,它定義了子類別如何通過主鍵關聯到父表。
<hibernate-mapping>
<class name="javamxj.inheritance.two.Vehicle" ...>
<id name="id" column="ID"><generator class="hilo"/></id>
<property name="name" column="name" length="24"/>
<joined-subclass name="javamxj.inheritance.two.Truck">
<key column="id"/>
<property name="load" column="載重" length="24"/>
</joined-subclass>
<joined-subclass name="javamxj.inheritance.two.Car">
<key column="id"/>
<property name="seat" column="載客" length="24"/>
</joined-subclass>
</class>
</hibernate-mapping>
執行 schemaexport 任務,資料庫將建立三張獨立的表:
Vehicle (ID, name)Car (id, 載客)Truck (id, 載重)子表的主鍵同時也是指向父表的外鍵,實現了正規化的資料結構。
編寫 Demo.java 進行資料新增與查詢:
public class Demo {
public static void main(String[] args) { ... }
public Demo() throws HibernateException {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session sess = sf.openSession();
Transaction tx = sess.beginTransaction();
Car car = new Car();
car.setName("奇瑞QQ");
car.setSeat("4人");
sess.save(car);
Truck truck = new Truck();
truck.setName("一汽解放");
truck.setLoad("10噸");
sess.save(truck);
tx.commit(); sess.close();
// 多態查詢
sess = sf.openSession();
tx = sess.beginTransaction();
List list = sess.find("from Vehicle");
for (Iterator it = list.iterator(); it.hasNext();) {
Vehicle v = (Vehicle) it.next();
System.out.println("車型:" + v.getName() + " 實際類別:" + v.getClass().getName());
}
tx.commit(); sess.close();
}
}
控制台輸出將顯示正確的子類別型別,證明多態查詢運作正常。
| 優點 | 缺點 |
|---|---|
|
|
下一篇將介紹「每個具體類一張表」的策略,敬請期待。