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

Hibernate 繼承映射完全指南(六):Joined Subclass 策略深度解析

     編輯:Java 相關知識

Joined Subclass(每類一表/連接繼承) 是最符合關係範式、支援多態查詢與關聯的標準策略。父類一表,每個子類一表,子表主鍵同時是指向父表的外鍵。本文詳細講解映射配置、SQL 生成、持久化操作與效能特徵。

表結構設計

  • EMPLOYEES (父表) — ID(PK), NAME, COMPANY_ID(FK)
  • HOURLY_EMPLOYEES (子表) — EMPLOYEE_ID(PK, FK→EMPLOYEES), RATE
  • SALARIED_EMPLOYEES (子表) — EMPLOYEE_ID(PK, FK→EMPLOYEES), SALARY

映射文件:Employee.hbm.xml 統一映射

<hibernate-mapping>
  <class name="mypack.Employee" table="EMPLOYEES">
    <id name="id" column="ID"><generator class="increment"/></id>
    <property name="name" column="NAME"/>
    <many-to-one name="company" column="COMPANY_ID" class="mypack.Company"/>

    <!-- 子類映射內嵌在父類映射中 -->
    <joined-subclass name="mypack.HourlyEmployee" table="HOURLY_EMPLOYEES">
      <key column="EMPLOYEE_ID"/> <!-- PK+FK -->
      <property name="rate" column="RATE" type="double"/>
    </joined-subclass>

    <joined-subclass name="mypack.SalariedEmployee" table="SALARIED_EMPLOYEES">
      <key column="EMPLOYEE_ID"/>
      <property name="salary" column="SALARY" type="double"/>
    </joined-subclass>
  </class>
</hibernate-mapping>

關鍵點:<key column="EMPLOYEE_ID"/> 聲明子表主鍵兼外鍵列。子類無需獨立映射文件,初始化時僅註冊父類 config.addClass(Employee.class) 即可。

多態查詢 SQL 分析

// 查詢所有 HourlyEmployee (內連接)
SELECT * FROM HOURLY_EMPLOYEES he INNER JOIN EMPLOYEES e ON he.EMPLOYEE_ID=e.ID;

// 查詢所有 Employee (左外連接,多態)
SELECT * FROM EMPLOYEES e
  LEFT JOIN HOURLY_EMPLOYEES he ON e.ID=he.EMPLOYEE_ID
  LEFT JOIN SALARIED_EMPLOYEES se ON e.ID=se.EMPLOYEE_ID;

Hibernate 根據子表 EMPLOYEE_ID 是否為 NULL 判斷實例類型:非 NULL → 對應子類實例。

多態關聯:Company → Employees 集合

映射 <one-to-many class="Employee"/> 即可支援多態集合。配合 lazy="true" 需手動 Hibernate.initialize(company.getEmployees()) 或配置 fetch="join" 迫切加載。

保存操作:雙表 INSERT

Employee emp = new HourlyEmployee("Mary", 300, company);
session.save(emp);

生成 SQL:

INSERT INTO EMPLOYEES (ID, NAME, COMPANY_ID) VALUES (5, 'Mary', 1);
INSERT INTO HOURLY_EMPLOYEES (EMPLOYEE_ID, RATE) VALUES (5, 300);

共享同一主鍵值 (5),事務保證原子性。

獨立映射文件寫法(可選)

若拆分 HourlyEmployee.hbm.xml,需顯式聲明 extends="mypack.Employee",且初始化順序必須父類先於子類:

config.addClass(Company.class).addClass(Employee.class).addClass(HourlyEmployee.class);

順序顛倒會拋 HibernateMappingException。

優缺點總結

優點缺點
✅ 完全符合 3NF 範式
✅ 支援多態查詢/關聯
✅ 非空約束可加在子表字段
✅ 父表無稀疏列
❌ 多態查詢需多表 JOIN,效能遜於單表
❌ 保存/更新涉及多表操作
❌ 映射配置相對複雜

適用場景

  • 嚴格要求數據完整性、外鍵約束的企業級應用
  • 繼承層級較深、子類擁有大量獨有字段
  • 頻繁進行多態查詢但數據量中等(可配合二級緩存優化)

Joined Subclass 是「正規化建模」與「物件多態」的最佳平衡點,掌握其連接查詢機制對性能調優至關重要。

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