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

Hibernate 繼承映射完全指南(五):單表策略運行實戰與 SQL 分析

     編輯:Java 相關知識

單表策略 將整個繼承體系映射到一張表,通過判別欄區分子類型。本文通過實戰代碼演示其查詢、加載、保存行為及生成 SQL,揭示「查詢效能最強但表結構妥協」的特性。

表結構:EMPLOYEES

欄位:ID(PK), NAME, RATE, SALARY, EMPLOYEE_TYPE(判別欄), COMPANY_ID(FK)

判別欄值:'HE' = HourlyEmployee, 'SE' = SalariedEmployee。子類專有欄位 (RATE/SALARY) 在另一類型記錄中為 NULL。

映射配置:<discriminator> + <subclass>

<class name="mypack.Employee" table="EMPLOYEES">
  <id name="id" column="ID"><generator class="increment"/></id>
  <discriminator column="EMPLOYEE_TYPE" type="string"/> <!-- 關鍵 -->
  <property name="name" column="NAME"/>
  <many-to-one name="company" column="COMPANY_ID" class="mypack.Company"/>

  <subclass name="mypack.HourlyEmployee" discriminator-value="HE">
    <property name="rate" column="RATE" type="double"/>
  </subclass>
  <subclass name="mypack.SalariedEmployee" discriminator-value="SE">
    <property name="salary" column="SALARY" type="double"/>
  </subclass>
</class>

運行實戰與 SQL 解析

1. 查詢 HourlyEmployee (單表過濾)

List results = session.find("from HourlyEmployee");

SQL:SELECT * FROM EMPLOYEES WHERE EMPLOYEE_TYPE='HE';

✅ 無 Join,極快。同時加載關聯的 Company (N+1 或 Join Fetch)。

2. 多態查詢所有 Employee

List results = session.find("from Employee");

SQL:SELECT * FROM EMPLOYEES;

Hibernate 讀取 EMPLOYEE_TYPE 實例化對應子類對象。✅ 單表全掃描,多態查詢效能最優。

3. 多態關聯:Company.load() + employees 集合

配置 lazy="true" 時需手動初始化:

Company c = (Company) session.load(Company.class, id);
Hibernate.initialize(c.getEmployees()); // 觸發加載

生成 SQL 同多態查詢,按 COMPANY_ID 過濾。

4. 保存 HourlyEmployee

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

SQL:INSERT INTO EMPLOYEES (ID, NAME, RATE, EMPLOYEE_TYPE, COMPANY_ID) VALUES (5, 'Mary', 300, 'HE', 1);

SALARY 欄位自動為 NULL。✅ 單 INSERT,效能最優。

核心優缺點

優點缺點
🚀 多態查詢/關聯效能最佳 (無 Join)
🚀 保存/更新單表操作
🚀 映射配置簡單
🛑 違反 3NF (稀疏表、大量 NULL)
🛑 子類非空字段無法加 NOT NULL 約束
🛑 表結構隨繼承擴展而膨脹
🛑 判別欄需額外維護

適用場景

  • 繼承樹淺、子類字段少、極高頻多態查詢
  • 讀多寫少、可容忍數據冗餘換取查詢速度
  • 原有系統重構,避免大幅修改表結構

避坑指南

  1. 判別欄索引:為 EMPLOYEE_TYPE 建立索引,加速多態查詢過濾。
  2. 字段命名衝突:不同子類不可有同名非繼承字段(會衝突)。
  3. 大字段慎用:CLOB/BLOB 等大字段會嚴重拖慢全表掃描,拆分到單獨表更佳。

單表策略是「以空間換時間」的經典權衡,理解其 SQL 生成機制有助於在架構評審中做出正確選型。

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