JPA 複合鍵實作指南

在使用 JPA 進行資料庫映射時,有些情境需要使用複合主鍵(Composite Key),特別是當實體間存在關聯關係且這些關聯本身也是主鍵的一部分時。本文將介紹如何使用 @IdClass 註解來實現複合主鍵,並著重說明如何處理嵌套的複合主鍵關係。

複合主鍵類別的定義

首先,我們需要定義代表複合主鍵的類別:

class PartPK implements Serializable {
     private String partId;
     private String orgId;

     // 此處省略必要的構造函數、equals和hashCode方法
}

class StockPK implements Serializable {
  private String storeId;
  private PartPK part;

  // 此處省略必要的構造函數、equals和hashCode方法
}

實體類別的實作

接著,我們實作對應的實體類別並添加適當的 JPA 註解:

@Entity
@Table(name = "parts") 
@IdClass(PartPK.class)
class Part implements Serializable {
    @Id
    @Column(name = "PART_ID")
    private String partId;

    @Id
    @Column(name = "PART_ORGANIZATION_ID")
    private String orgId;

    // 其他欄位與方法...
}

@Entity 
@Table(name = "stocks") 
@IdClass(StockPK.class)
class Stock implements Serializable {
    @Id
    @Column(name = "STORE_ID")
    private String storeId;

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
        @JoinColumn(name = "STOCK_PART_ID", referencedColumnName = "PART_ID"),
        @JoinColumn(name = "STOCK_PART_ORGANIZATION_ID", referencedColumnName = "PART_ORGANIZATION_ID"),
    })
    private Part part;

    // 其他欄位與方法...
}

JPA 複合主鍵實作重點

  1. 實作 Serializable 介面:所有主鍵類別都必須實作 Serializable 介面。

  2. 使用 @IdClass 註解:在實體類別上使用此註解指定對應的複合主鍵類別。

  3. 標記 @Id 欄位:實體類別中組成複合主鍵的所有欄位都必須標記為 @Id

  4. 使用 @JoinColumns:當複合主鍵中包含對另一個實體的關聯時(如範例所示),@JoinColumns 允許將多個欄位映射到被參照實體的 ID 欄位。

  5. 實作 equals() 和 hashCode():主鍵類別應基於所有構成複合主鍵的欄位正確實作 equals()hashCode() 方法。

  6. 無參數建構函數:主鍵類別必須具有無參數建構函數。

此方法的優勢

  • 允許自然地建模複雜的主鍵關聯
  • 支援在具有複合關聯的實體之間進行導航
  • 在資料庫層面維護參照完整性約束
  • 啟用 JPA 的實體管理功能,例如級聯操作

這種模式在建模庫存系統、多租戶應用程式,或任何需要通過多個欄位(包括對其他實體的參照)來識別實體的領域中特別有用。