實體唯一標識(主鍵)的自動生成是持久層核心需求。OpenJPA 提供四種策略,配合 @GeneratedValue、@SequenceGenerator、@TableGenerator 三大註解,滿足不同資料庫特性與業務場景。
@GeneratedValue(strategy, generator):主鍵生成入口,strategy 指定策略枚舉(AUTO、IDENTITY、SEQUENCE、TABLE),generator 關聯生成器名稱。@SequenceGenerator(name, sequenceName, initialValue, allocationSize):序列生成器配置。@TableGenerator(name, table, schema, catalog, pkColumnName, valueColumnName, pkColumnValue, initialValue, allocationSize):表生成器配置。GenerationType.AUTO)預設策略。OpenJPA 自動建立表 OPENJPA_SEQUENCE_TABLE (欄位 ID, SEQUENCE_VALUE) 維護全域序列。支援數值型與字串型(UUID)主鍵:
allocationSize=50),減少資料庫往返。同一 EntityManagerFactory 範圍內共享緩存,關閉時未用 ID 丟失(導致不連續)。所有容器管理實體共享同一序列(Dog=1, Fish=2...)。generator="uuid-string" (16 位) 或 "uuid-hex" (32 位 16 進制),無需資料庫支援,適合分布式環境。@Id @GeneratedValue(strategy=GenerationType.AUTO, generator="uuid-hex")
private String id; // 32 位十六進制 UUID
GenerationType.IDENTITY)適用 MySQL、SQL Server、DB2、Derby、HSQL 等支援 AUTO_INCREMENT/IDENTITY 的資料庫。資料庫負責生成,插入後由 JDBC getGeneratedKeys() 取回。無緩存,每次插入必訪問資料庫。
-- MySQL 建表
CREATE TABLE ANIMAL (ID INTEGER AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(255));
@Entity
public class Animal {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
}
GenerationType.SEQUENCE)適用 Oracle、PostgreSQL 等支援 SEQUENCE 物件的資料庫。需預先建立序列,配置 @SequenceGenerator:
-- Oracle 建序列
CREATE SEQUENCE HELLOWORLDSEQUENCE START WITH 0 INCREMENT BY 1 CACHE 50;
@Entity
public class Animal {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SeqGenerator")
@SequenceGenerator(name="SeqGenerator", sequenceName="HELLOWORLDSEQUENCE", allocationSize=50)
private long id;
}
allocationSize 對應序列 CACHE,預設 50,需與資料庫定義一致,否則導致 ID 跳躍或衝突。
GenerationType.TABLE)通用性最強,不依賴特定資料庫特性。維護一張序列表(預設 OPENJPA_SEQUENCES_TABLE),欄位 ID(PK)、SEQUENCE_VALUE。透過 @TableGenerator 自定義表/欄位/特徵值:
-- 自定義序列表
CREATE TABLE MY_KEYS (KEYID VARCHAR(255) PRIMARY KEY, KEYVALUE BIGINT);
@Entity
public class Animal {
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="TableGenerator")
@TableGenerator(name="TableGenerator", table="MY_KEYS",
pkColumnName="KEYID", valueColumnName="KEYVALUE", pkColumnValue="ANIMALID", allocationSize=50)
private long id;
}
多實體可共享同一 pkColumnValue 實現全域序列,或各自獨立序列。
無論何種策略,業務代碼完全一致——無需手動設定 ID:
Animal animal = new Animal();
animal.setName("ba guai!");
em.persist(animal); // ID 由提供者自動生成並回填
| 場景 | 推薦策略 | 理由 |
|---|---|---|
| MySQL/SQL Server/DB2 | IDENTITY | 原生支援、零配置、效能佳 |
| Oracle/PostgreSQL | SEQUENCE | 原生序列物件、高併發效能最優 |
| 跨資料庫移植/無特殊支援 | TABLE | 純標準 SQL 實現、完全可移植 |
| 分布式/無中心協調 | AUTO (UUID) | 無需資料庫協調、全域唯一 |
| 簡單原型/測試 | AUTO (預設) | 零配置、開箱即用 |
OpenJPA 靈活的主鍵生成機制,通過標準註解抽象資料庫差異。理解 allocationSize 緩存機制、共享序列行為、UUID 適用場景,對避免主鍵衝突、效能調優、跨庫移植至關重要。實務上優先選擇資料庫原生機制 (IDENTITY/SEQUENCE),次選 TABLE,特殊場景用 UUID。