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

JPA 主鍵生成策略完全指南:Table、Sequence、Identity、AUTO 與複合主鍵

     編輯:Java 相關知識

Java EE 專案持久層雖隨應用伺服器異有不同持久化引擎實現,但 JPA 規範統一了主鍵生成策略。掌握核心策略,即可從容應對各類具體場景。

四大標準策略

1. Table 策略(可移植性最佳)

持久化引擎使用關係資料庫表生成主鍵,所有資料庫均支援。

自定義表生成器:

@Entity
public class PrimaryKey_Table {
    @TableGenerator(
        name = "PK_SEQ",
        table = "SEQUENCE_TABLE",
        pkColumnName = "SEQUENCE_NAME",
        valueColumnName = "SEQUENCE_COUNT"
    )
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "PK_SEQ")
    private Long id;
    // Getters/Setters
}
  • name:生成器名稱 (PK_SEQ),供 generator 引用。
  • table:儲存主鍵的表 (SEQUENCE_TABLE),資料庫需存在。
  • pkColumnName:該表主鍵欄位名。
  • valueColumnName:儲存最後生成值的欄位。

使用持久化引擎預設表:

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;

GlassFish 預設:table=SEQUENCE、pkColumnName=SEQ_NAME、valueColumnName=SEQ_COUNT。不同引擎預設值不同。

2. Sequence 策略(Oracle、PostgreSQL 等原生支援)

調用資料庫內建 Sequence 機制。

public class PK_Sequence implements Serializable {
    @SequenceGenerator(name = "PK_SEQ_TBL", sequenceName = "PK_SEQ_NAME")
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PK_SEQ_TBL")
    private Long id;
}

@SequenceGenerator 關鍵屬性:

  • name:生成器名。
  • sequenceName:資料庫 Sequence 名。
  • initialValue:初始值 (預設 1)。
  • allocationSize:持久化引擎從 Sequence 讀取值的快取大小 (預設 50),效能優化關鍵。

3. Identity 策略(MySQL、SQL Server、DB2 等自增欄)

資料庫自增欄生成主鍵,僅需指定策略:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

4. AUTO 策略(交由持久化引擎決定)

引擎從 Table/Sequence/Identity 三者選擇。GlassFish 採 Table。顯式或隱式均可:

@GeneratedValue(strategy = GenerationType.AUTO)
// 或
@GeneratedValue
// 或什麼都不寫(預設即 AUTO)

複合主鍵:@EmbeddedId 與 @IdClass 兩種方案

實務常遇歷史表複合主鍵。JPA 2.0 要求:主鍵欄位置於獨立主鍵類,重寫 equals()/hashCode()、實作 Serializable、無參建構子。

方案一:@EmbeddedId

主鍵類標註 @Embeddable:

@Embeddable
public class NewsId implements Serializable {
    private String title;
    private String language;
    // getters/setters
    @Override public boolean equals(Object obj) { /* 比較 title + language */ }
    @Override public int hashCode() { /* 組合雜湊 */ }
}

實體類直接嵌入:

@Entity
public class News implements Serializable {
    @EmbeddedId
    private NewsId id;
    private String content;
    // Getters/Setters
}

生成表結構:PRIMARY KEY (TITLE, LANGUAGE)。
查詢寫法:SELECT n.id.title FROM News n。

方案二:@IdClass

主鍵類不需 @Embeddable,其餘要求相同(去掉註解即可)。

實體類宣告 @IdClass 並重複定義主鍵欄位且逐一標註 @Id:

@Entity
@IdClass(NewsId.class)
public class News implements Serializable {
    @Id private String title;
    @Id private String language;
    private String content;
    // Getters/Setters
}

生成表結構相同。查詢寫法:SELECT n.title FROM News n(較簡潔)。
注意:重複欄位定義必須與主鍵類完全一致。

總結與選型建議

策略適用場景可移植性效能備註
Table跨資料庫部署、無原生 Sequence/Identity最高需額外表查詢/更新,可透過 allocationSize 優化
SequenceOracle、PostgreSQL、DB2 等支援 Sequence高allocationSize 預設 50 減少資料庫往返
IdentityMySQL、SQL Server、DB2 自增欄中插入後才知主鍵值,批次插入受限
AUTO不想綁定具體策略、交由引擎決定最高實際行為視引擎而異

複合主鍵:@EmbeddedId 語義清晰(主鍵即值物件),@IdClass 查詢稍簡潔且符合某些習慣。根據團隊偏好與既有代碼風格選擇。

掌握上述策略,持久層開發即能「以不變應萬變」。

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