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

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

     編輯:J2EE

前言

JPA/Hibernate 支援三種繼承映射策略,對應資料庫不同的表結構設計。透過 @Inheritance 註解在父類別指定策略,搭配 @DiscriminatorColumn、@DiscriminatorValue、@PrimaryKeyJoinColumn 等註解微調細節。

策略一:每類一表

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class A { @Id @GeneratedValue private int id; private String aname; }

@Entity
public class B extends A { private String bname; }

@Entity
public class C extends A { private String cname; }

生成 DDL:

create table A (id integer not null auto_increment, aname varchar(255), primary key (id))
create table B (id integer not null, aname varchar(255), bname varchar(255), primary key (id))
create table C (id integer not null, aname varchar(255), cname varchar(255), primary key (id))

特點:各子表獨立包含父屬性欄位,無關聯;查詢父類需 UNION 所有子表,效能較差;不支援 IDENTITY 自增策略 (需用 TABLE 或 SEQUENCE)。

策略二:單表策略

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "mytype", discriminatorType = DiscriminatorType.STRING)
public class A { ... }

@Entity
@DiscriminatorValue("btype")
public class B extends A { ... }

@Entity
@DiscriminatorValue("ctype")
public class C extends A { ... }

生成 DDL:

create table A (id integer not null auto_increment, aname varchar(255), mytype varchar(31), bname varchar(255), cname varchar(255), primary key (id))

特點:所有類別共用一表,新增判別欄位 (DTYPE 或自訂 mytype);查詢效能最好,但子類特有欄位必須允許 NULL;大量子類導致表欄位膨脹。

策略三:連接子類策略

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class A { @Id @GeneratedValue private int id; private String aname; }

@Entity
@PrimaryKeyJoinColumn(name = "bid") // 可自訂子表 PK/FK 欄位名
public class B extends A { private String bname; }

@Entity
public class C extends A { private String cname; }

生成 DDL:

create table A (id integer not null auto_increment, aname varchar(255), primary key (id))
create table B (bname varchar(255), bid integer not null, primary key (bid))
create table C (cname varchar(255), id integer not null, primary key (id))
alter table B add constraint FK_B_A foreign key (bid) references A (id)
alter table C add constraint FK_C_A foreign key (id) references A (id)

特點:父表存共同屬性,子表存特有屬性 + PK/FK;符合正規化,查詢需 JOIN;支援 @PrimaryKeyJoinColumn 自訂 FK 欄位名,但不能關聯父表非主鍵欄位 (會報錯 SecondaryTable JoinColumn cannot reference a non primary key)。

非持久化父類別

使用 @MappedSuperclass,父類別不對應資料表,僅提供共同屬性給子類繼承:

@MappedSuperclass
public class BaseEntity { @Id @GeneratedValue private Long id; private String createdBy; }

@Entity
public class User extends BaseEntity { private String username; }

生成 DDL:User 表直接包含 id、createdBy、username,無 BaseEntity 表。

屬性覆寫

子類別可用 @AttributeOverride、@AssociationOverride 覆寫父類欄位定義 (如欄位名、長度等)。

總結

策略表數量查詢效能正規化適用場景
TABLE_PER_CLASS每類一表差 (UNION)低子類差異大、很少多型查詢父類
SINGLE_TABLE單表最好低繼承層次淺、欄位少、高頻多型查詢
JOINED父表+各子表中 (JOIN)高需正規化、子類擴充性強
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved