| 策略 | 資料表數 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| Table per Concrete Class | 每個具體類一張表 | 無 JOIN,查詢快;結構簡單 | 無法共享主鍵;多型查詢需 UNION;修改父類欄位需改所有表 | 繼承層次淺、欄位差異大、極少多型查詢 |
| Table per Class Hierarchy | 單表 | 查詢最快(無 JOIN);結構簡單 | 子類欄位必須 nullable;表欄位多、稀疏;歧視欄位佔空間 | 繼承層次淺、子類欄位少、頻繁多型查詢 |
| Table per Subclass | 父類一表 + 每子類一表 | 正規化程度高;無 nullable 問題;支援外鍵約束 | 查詢需 JOIN;多型查詢效能較差 | 繼承層次深、子類欄位多、重視資料完整性 |

CREATE TABLE defaultuser (id PK, name, someProperty);
CREATE TABLE poweruser (id PK, name, otherProperty);
<class>,無共同父類映射<class name="DefaultUser" table="defaultuser"> ... </class>
<class name="PowerUser" table="poweruser"> ... </class>
from com.hb3.pack_08.model.User -- Hibernate 產生 UNION ALL 查詢
注意:若查詢 from java.lang.Object 會掃描資料庫所有表,極其危險,嚴禁生產使用。

CREATE TABLE user (
id PK, userType VARCHAR(50) NOT NULL, -- 歧視欄位
name, someProperty, otherProperty
);
<discriminator>,子類用 <subclass><class name="User" table="user">
<id name="id" .../>
<discriminator column="userType" type="string"/>
<property name="name"/>
<subclass name="DefaultUser" discriminator-value="Default">
<property name="someProperty"/>
</subclass>
<subclass name="PowerUser" discriminator-value="Power">
<property name="otherProperty"/>
</subclass>
</class>
所有子類欄位在同一表,**必須允許 NULL**。

CREATE TABLE user (id PK, name);
CREATE TABLE defaultuser (id PK FK, someProperty);
CREATE TABLE poweruser (id PK FK, otherProperty);
<class>,子類用 <joined-subclass><class name="User" table="user">
<id name="id" .../>
<property name="name"/>
<joined-subclass name="DefaultUser" table="defaultuser">
<key column="id"/>
<property name="someProperty"/>
</joined-subclass>
<joined-subclass name="PowerUser" table="poweruser">
<key column="id"/>
<property name="otherProperty"/>
</joined-subclass>
</class>
子類表主鍵同時是指向父表的外鍵,<key column="id"/> 對應父表主鍵。
三種策略下,from User 皆能查出所有子類實例,但 SQL 差異巨大:
UNION ALL 多表查詢WHERE userType IN (...)LEFT OUTER JOIN 多表關聯