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

Eclipse 快速上手 Hibernate:繼承映射策略之「每個具體類一張表」

     編輯:Java 相關知識

策略核心

抽象基類不映射表,每個具體子類映射獨立表,表包含繼承自基類的所有欄位。 適合多態查詢較少、子類差異大、報表查詢頻繁的場景。

類別設計

抽象基類:Person.java


package javamxj.inheritance.three;

public abstract class Person {
    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.class 標記,不生成映射檔、不建表。

具體子類:Student.java


package javamxj.inheritance.three;

/** @hibernate.class table="Student" */
public class Student extends Person {
    private String studentNumber;

    /** @hibernate.property length="24" */
    public String getStudentNumber() { return studentNumber; }
    public void setStudentNumber(String studentNumber) { this.studentNumber = studentNumber; }
}

具體子類:Professor.java


package javamxj.inheritance.three;

/** @hibernate.class table="Professor" */
public class Professor extends Person {
    private int salary;

    /** @hibernate.property */
    public int getSalary() { return salary; }
    public void setSalary(int salary) { this.salary = salary; }
}

生成的映射檔 (各自獨立)

Student.hbm.xml



  
  
    ← 繼承欄位內聯

Professor.hbm.xml



  
  
    ← 繼承欄位內聯

資料庫 Schema


CREATE TABLE Student (
  ID BIGINT NOT NULL,
  studentNumber VARCHAR(24),
  name VARCHAR(24),
  PRIMARY KEY (ID)
);

CREATE TABLE Professor (
  ID BIGINT NOT NULL,
  salary INTEGER,
  name VARCHAR(24),
  PRIMARY KEY (ID)
);

無 Person 表,子表自包含所有欄位。

測試與多態查詢限制


List list = session.find("from Person"); // HQL 查詢基類
for (Iterator it = list.iterator(); it.hasNext();) {
    Person p = (Person) it.next();
    System.out.println(p.getName() + " -> " + p.getClass().getName());
}

關鍵限制:Hibernate 以 **UNION** 方式查詢所有子表,無法保證 ID 唯一性跨表 (需業務層保證或共用 hilo 生成器)。多態關聯 (如 many-to-one 指向 Person) **不支援**。

優缺點總結

優點缺點
  • 報表查詢極簡單:單表含所有資訊
  • 無聯結,讀取效能最好
  • 子類獨立演進,互不影響
  • 基類修改 → 所有子表結構同步變更 (DDL 維護重)
  • 跨表 ID 唯一性難保證
  • 多態查詢/關聯受限 (Union 查詢慢、不支援外鍵)
  • 欄位冗餘 (name 重複儲存)

適用場景建議

  • ✅ 子類差異極大、共用欄位少
  • ✅ 以單表查詢/報表為主、極少多態操作
  • ✅ 歷史系統重構、不想動基類表結構
  • ❌ 需要多態關聯、跨子類唯一性約束
  • ❌ 基類欄位多、頻繁變更

三大策略對比速查

策略表數量多態支援空間效率修改基類影響報表友好度
單表 (Table per Hierarchy)1最好低 (大量 NULL)小 (加欄位)好
每子類一表 (Joined Subclass)1+N好高 (正規化)中 (需遷移)需 View
每具體類一表N差 (Union)中 (冗餘)大 (全子表改)最好

結語

「每個具體類一張表」以**空間換查詢簡單**,犧牲多態與維護靈活性。選型時以**業務存取模式**為準:報表多、多態少 → 選此;多態核心、結構常變 → 選 Joined Subclass;簡單層次、效能優先 → 選單表。下一篇將介紹**組件 (Component) 映射**。

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