首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate 繼承關係映射三大策略深度解析

     編輯:Java 相關知識

在領域模型中,繼承關係是核心概念之一。以 Employee 抽象類別為例,衍生出 HourlyEmployee(時薪員工)與 SalariedEmployee(月薪員工)兩個具體子類別,構成繼承樹。資料庫不支援繼承,Hibernate 提供三種映射策略將物件繼承轉換為關聯式資料模型。

多態查詢與多態關聯

多態讓 Employee 變數可引用兩種子類別實例:

List employees = businessService.findAllEmployees();
for (Employee e : employees) {
    if (e instanceof HourlyEmployee)
        System.out.println(e.getName() + " " + ((HourlyEmployee)e).getRate());
    else
        System.out.println(e.getName() + " " + ((SalariedEmployee)e).getSalary());
}

findAllEmployees() 回傳包含兩種子類別的集合,即多態查詢。Company 到 Employee 為多態關聯(集合含子類別實例),反向則非多態。

三種映射策略比較

策略資料表結構支援多態優點缺點
每個具體類別一張表
(Table per Concrete Class)
HourlyEmployee、SalariedEmployee 各自獨立表,包含所有繼承欄位 不支援 查詢單一類別效能最好,無 JOIN 無法多態查詢,結構重複,修改父類欄位需改所有表
根類別一張表
(Table per Class Hierarchy)
單一 Employee 表,加 discriminator 欄位區分子類型 支援 多態查詢快(無 JOIN),結構簡單 子類別特有欄位須設 NULL,資料完整性較難維護,表膨脹
每個類別一張表
(Table per Subclass)
Employee 表 + HourlyEmployee/SalariedEmployee 表,透過 FK 關聯 支援 資料正規化,完整性佳,欄位不重複 多態查詢需 JOIN,效能較差;結構較複雜

策略選擇指引

  • 具體類別表:繼承樹淺、極少多態查詢、效能極度敏感
  • 根類別表:繼承樹淺、子類別欄位少、頻繁多態查詢
  • 子類別表:繼承樹深、子類別欄位多、重視資料正規化

Hibernate 映射配置範例

根類別表(單表策略):

<class name="Employee" table="EMPLOYEE">
  <id name="id" column="EMP_ID"><generator class="native"/></id>
  <discriminator column="EMP_TYPE" type="string"/>
  <property name="name" column="NAME"/>
  <subclass name="HourlyEmployee" discriminator-value="HOURLY">
    <property name="rate" column="HOURLY_RATE"/>
  </subclass>
  <subclass name="SalariedEmployee" discriminator-value="SALARIED">
    <property name="salary" column="MONTHLY_SALARY"/>
  </subclass>
</class>

子類別表(聯結策略):

<class name="Employee" table="EMPLOYEE">
  <id name="id" column="EMP_ID"><generator class="native"/></id>
  <property name="name" column="NAME"/>
  <joined-subclass name="HourlyEmployee" table="HOURLY_EMP">
    <key column="EMP_ID"/>
    <property name="rate" column="HOURLY_RATE"/>
  </joined-subclass>
  <joined-subclass name="SalariedEmployee" table="SALARIED_EMP">
    <key column="EMP_ID"/>
    <property name="salary" column="MONTHLY_SALARY"/>
  </joined-subclass>
</class>

總結

無銀彈,三種策略各有取捨。實務上常混合使用:核心領域模型採用子類別表保證正規化;高頻查詢、唯讀報表模型可考慮根類別表或具體類別表換取效能。理解多態查詢與關聯的語意差異,是選型關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved