Oracle 12c 前無 `AUTO_INCREMENT`/`IDENTITY` 列,主鍵通常通過 **Sequence (序列) + Trigger (觸發器)** 實現自增。Hibernate 需正確映射此機制。
| 策略 | 適用場景 | Hibernate 註解 | 優缺點 |
|---|---|---|---|
| SEQUENCE (推薦) | Oracle、PostgreSQL、DB2、H2 | `@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_gen")` `@SequenceGenerator(name = "seq_gen", sequenceName = "SEQ_USER_ID", allocationSize = 1)` | ✅ 標準 JPA、性能好 (預分配)、可控 ⚠️ 需數據庫預建 Sequence |
| IDENTITY | MySQL、SQL Server、PostgreSQL 10+、Oracle 12c+ (GENERATED AS IDENTITY) | `@GeneratedValue(strategy = GenerationType.IDENTITY)` | ✅ 簡單、無需 Sequence ❌ Oracle 12c 前不支持、批量插入性能差 (無法 JDBC 批處理) |
| TABLE (通用、不推薦) | 所有支持表的數據庫 | `@GeneratedValue(strategy = GenerationType.TABLE, generator = "tbl_gen")` `@TableGenerator(...)` | ✅ 純表模擬、完全可移植 ❌ 性能極差 (行鎖競爭)、不推薦高併發 |
| AUTO (默認) | 由 Dialect 決定 | `@GeneratedValue(strategy = GenerationType.AUTO)` | Oracle Dialect 通常退回 SEQUENCE,但行為不確定,**生產環境禁用** |
| 手動分配 (assigned) | 業務主鍵 (訂單號、UUID) | `@Id` `@GeneratedValue(strategy = GenerationType.ASSIGNED)` 或無註解 | 應用層完全控制 (UUID、Snowflake、業務編碼) |
CREATE SEQUENCE SEQ_USER_ID
START WITH 1
INCREMENT BY 1
NOCACHE -- 或 CACHE 20 (性能更好,但重啟可能跳號)
NOCYCLE;
@Entity
@Table(name = "T_USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userSeqGen")
@SequenceGenerator(
name = "userSeqGen", // 對應 generator
sequenceName = "SEQ_USER_ID", // 數據庫序列名
allocationSize = 50 // 【關鍵】預分配 50 個 ID,減少 DB 交互
)
@Column(name = "USER_ID")
private Long id;
// 其他字段...
}
✅ **性能提升 50 倍** (批量插入場景)。
⚠️ **數據庫序列 INCREMENT BY 必須等於 allocationSize**,否則 ID 跳躍/重複。
-- 數據庫
CREATE SEQUENCE SEQ_USER_ID INCREMENT BY 1; -- 錯誤!應為 50
-- Java
allocationSize = 50; -- 內存以為每次拿 50 個,實際 DB 每次只加 1
-- 結果:內存生成 1..50,下次 DB 返回 2,內存生成 51..100,DB 返回 3... 主鍵衝突!
**鐵律:`sequence INCREMENT BY = allocationSize`**。
<id name="id" column="USER_ID">
<generator class="sequence">
<param name="sequence">SEQ_USER_ID</param>
<param name="allocationSize">50</param>
</generator>
</id>
Oracle 下 Hibernate 主鍵生成:**首選 `GenerationType.SEQUENCE` + `@SequenceGenerator`**,務必設置 `allocationSize` (建議 50~100) 並與數據庫 `INCREMENT BY` 保持一致。Oracle 12c+ 可用 `IDENTITY` 簡化,但批量性能不如 Sequence。禁用 `AUTO` 和 `TABLE` 策略。