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

EJB3 單表繼承策略:以判別欄位將單表映射為多實體

     編輯:J2EE

前言

在 EJB 1.x/2.x 時代,無法透過繼承將單一資料表拆分映射為多個實體 Bean。EJB3 引入 InheritanceType.SINGLE_TABLE 策略,配合 @DiscriminatorColumn 與 @DiscriminatorValue,即可輕鬆實現「一張表、多個實體」的對應。

資料表結構

t_accounts 表包含以下欄位:

  • account_id(主鍵)、balance(餘額)、account_type(判別欄位,C=活期、S=儲蓄)
  • overdraft_limit(僅活期使用)、interest_rate(僅儲蓄使用)
t_accounts 表結構與資料

實體 Bean 實作

1. 父類別 Account

@Entity
@Table(name = "t_accounts")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "account_type")
public class Account {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "account_id")
    protected String id;

    protected float balance;

    @Column(name = "account_type", insertable = false, updatable = false)
    protected String type;

    // Getter/Setter 略...
}

關鍵點:

  1. @Inheritance(strategy = SINGLE_TABLE):所有子類別共用同一張表。
  2. @DiscriminatorColumn(name = "account_type"):指定判別欄位。
  3. insertable = false, updatable = false:判別欄位由容器自動維護,不可手動寫入,否則會拋出 MappingException。

2. 活期帳戶 CheckingAccount

@Entity
@DiscriminatorValue("C")
public class CheckingAccount extends Account {
    private double overdraftLimit;
    // Getter/Setter 略...
}

3. 儲蓄帳戶 SavingsAccount

@Entity
@DiscriminatorValue("S")
public class SavingsAccount extends Account {
    private double interestRate;
    // Getter/Setter 略...
}

子類別透過 @DiscriminatorValue 宣告各自對應的判別值,持久化時容器自動填入 account_type。

測試程式碼

CheckingAccount ca = new CheckingAccount();
ca.setBalance(342);
ca.setOverdraftLimit(120);
em.persist(ca); // 自動設定 account_type = 'C'

SavingsAccount sa = new SavingsAccount();
sa.setBalance(200);
sa.setInterestRate(3.21);
em.persist(sa); // 自動設定 account_type = 'S'

優缺點分析

  • 優點:查詢無需 JOIN,效能最好;結構簡單。
  • 缺點:子類別專屬欄位在資料庫層面必須允許 NULL,導致空值浪費;不支援子類別專屬欄位加 NOT NULL 約束。

適用於子類別差異較小、欄位數較少的場景。

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