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

EJB 3 開發指南(11):JOINED 繼承策略 - 物理分表實作

     編輯:Java 相關知識

繼承映射策略中,JOINED 將父類與各子類分別映射到不同資料表,透過主鍵關聯查詢。適用於:子類擁有大量獨有欄位、需避免單表過多空值、子類資料存取頻率差異大的場景。本文完整示範資料表設計、實體類別定義與測試程式碼。

一、資料表結構設計

父表:t_myaccounts (共用欄位)

account_id (PK) | balance | account_type

t_myaccounts 表結構

子表:t_checkingaccount (活期專屬)

account_id (PK, FK) | overdraft_limit

t_checkingaccount 表結構

子表:t_savingsaccount (儲蓄專屬)

account_id (PK, FK) | interest_rate

t_savingsaccount 表結構

關鍵點:子表 account_id 同時為主鍵與外鍵,參考父表 account_id,實現 1:1 關聯。

二、實體類別定義

父類:Account

@Entity
@Table(name="t_myaccounts")
@Inheritance(strategy=InheritanceType.JOINED)
public class Account {
    protected String id;
    protected float balance;
    protected String type;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="account_id")
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public float getBalance() { return balance; }
    public void setBalance(float balance) { this.balance = balance; }

    @Column(name="account_type")
    public String getType() { return type; }
    public void setType(String type) { this.type = type; }
}

關鍵註解:@Inheritance(strategy=InheritanceType.JOINED) 啟用 JOINED 策略。

子類:MyCheckingAccount

@Entity
@Table(name="t_checkingaccount")
@PrimaryKeyJoinColumn(name="account_id")  // 指定共享主鍵欄位
public class MyCheckingAccount extends Account {
    private double overdraftLimit;

    public MyCheckingAccount() {
        setType("C");  // 建構子預設類型值
    }

    @Column(name="overdraft_limit")
    public double getOverdraftLimit() { return overdraftLimit; }
    public void setOverdraftLimit(double overdraftLimit) { this.overdraftLimit = overdraftLimit; }
}

子類:MySavingsAccount

@Entity
@Table(name="t_savingsaccount")
@PrimaryKeyJoinColumn(name="account_id")
public class MySavingsAccount extends Account {
    private double interestRate;

    public MySavingsAccount() {
        setType("S");
    }

    @Column(name="interest_rate")
    public double getInterestRate() { return interestRate; }
    public void setInterestRate(double interestRate) { this.interestRate = interestRate; }
}

三、測試程式碼

// 查詢活期帳戶餘額
System.out.println(
    ((MyCheckingAccount) em.createQuery("from MyCheckingAccount where id=12")
      .getSingleResult()).getBalance()
);

// 新增活期帳戶
MyCheckingAccount ca = new MyCheckingAccount();
ca.setBalance(342);
ca.setOverdraftLimit(120);
em.persist(ca);  // 自動寫入 t_myaccounts 與 t_checkingaccount

// 新增儲蓄帳戶
MySavingsAccount sa = new MySavingsAccount();
sa.setBalance(200);
sa.setInterestRate(321);
em.persist(sa);  // 自動寫入 t_myaccounts 與 t_savingsaccount

四、三大繼承策略對比

策略註解資料表數優點缺點適用場景
SINGLE_TABLE@Inheritance(SINGLE_TABLE)
@DiscriminatorColumn
1查詢快、無 Join空值多、欄位耦合欄位少、查詢頻繁、子類差異小
JOINED@Inheritance(JOINED)
@PrimaryKeyJoinColumn
1+N正規化、無空值、擴充性佳查詢需 Join、插入多表子類欄位多、差異大、存取頻率不同
TABLE_PER_CLASS@Inheritance(TABLE_PER_CLASS)N完全隔離、無 Join多型查詢慢、Union 查詢極少多型查詢、獨立演進

五、JOINED 策略效能提示

  • 查詢子類:自動 Inner Join 父表,單筆查詢影響較小
  • 多型查詢(from Account):產生 Left Outer Join 所有子表,資料量大時效能下降
  • 索引優化:確保父表 PK 與子表 PK/FK 皆有索引
  • 批次插入:大量資料匯入時考慮關閉交易日誌或使用原生 SQL

選擇建議

若系統以「查詢特定帳戶類型」為主(如查活期、查儲蓄),JOINED 是最佳平衡;若頻繁執行「查所有帳戶」多型報表,SINGLE_TABLE 或加上快取機制較佳。

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