Hibernate 提供豐富的主鍵生成策略(<generator>),通過在映射文件中配置即可將主鍵生成邏輯委託給框架或數據庫。本文系統梳理 11 種常用策略的原理、優缺點、適用數據庫及選型建議,助你在不同業務場景做出最優決策。
| 策略 | 底層依賴 | 類型 | 適用數據庫 | 集群安全 | 推薦指數 |
|---|---|---|---|---|---|
| increment | Hibernate 內存計數器 | long/short/int | 所有 | ❌ 單進程 | ⭐ |
| identity | 數據庫自增列 | long/short/int | MySQL, SQL Server, DB2, Sybase | ✅ | ⭐⭐⭐ |
| sequence | 數據庫 Sequence | long/short/int | Oracle, PostgreSQL, DB2, SAP DB | ✅ | ⭐⭐⭐ |
| hilo | 數據庫表 + 內存算法 | long/short/int | 所有 | ✅ | ⭐⭐ |
| seqhilo | Sequence + HiLo 算法 | long/short/int | Oracle, PostgreSQL 等支持 Sequence | ✅ | ⭐⭐ |
| uuid.hex | Hibernate 128-bit UUID | String(32) | 所有 | ✅ | ⭐⭐⭐⭐ |
| uuid.string | Hibernate 16-bit UUID | String(16) | 所有 | ✅ | ⭐⭐ |
| guid | 數據庫 GUID | String | SQL Server, MySQL | ✅ | ⭐⭐ |
| native | 自動選擇 identity/sequence/hilo | 視底層而定 | 所有 | ✅ | ⭐⭐⭐⭐ |
| assigned | 應用程序手動賦值 | 任意 | 所有 | 視業務而定 | ⭐ |
| foreign | 關聯表主鍵(一對一) | 任意 | 所有 | ✅ | ⭐⭐ |
原理:依賴數據庫 AUTO_INCREMENT (MySQL) 或 IDENTITY(1,1) (SQL Server)。插入時不指定主鍵,數據庫自動生成。
MySQL: CREATE TABLE t(id INT AUTO_INCREMENT PRIMARY KEY, ...); SQL Server: CREATE TABLE t(id INT IDENTITY(1,1) PRIMARY KEY, ...);
優點:零配置、性能高、無需額外表/序列。
缺點:Oracle 不支持;批量插入需 session.flush() 才能獲取生成的 ID;跨庫移植性稍弱。
原理:調用數據庫 SEQUENCE 對象(seq_name.NEXTVAL)。Hibernate 默認查找 hibernate_sequence,建議顯式指定:
<generator class="sequence"> <param name="sequence">MY_SEQ</param> </generator>
優點:支持批量獲取 ID(配合 allocationSize)、高併發性能優異。
缺點:MySQL/SQL Server 不支持;需額外創建 Sequence 對象。
原理:根據 dialect 自動選擇:MySQL/SQL Server → identity;Oracle/PostgreSQL → sequence;其他 → hilo。
優點:一套映射文件適配多種數據庫,遷移極其方便。
注意:若使用 Sequence/HiLo,所有表共享同一 Sequence/表,可能成為熱點。
原理:128-bit UUID(IP + JVM 啟動時間 + 系統時間 + 計數器),編碼為 32 位十六進制字符串。完全在 JVM 內生成,無任何數據庫交互。
優點:絕對唯一、無鎖競爭、分庫分表、微服務架構下最佳選擇。
缺點:主鍵長度 32 字符,索引體積大、範圍查詢無序、不利於人工閱讀。
原理:Hi/Lo 算法將 ID 拆分為「高位(數據庫)」+「低位(內存)」。
hilo 需建表 hibernate_unique_key(next_hi INT);
seqhilo 則用 Sequence 提供高位。
每次從數據庫取一個高位值,內存中可生成 max_lo(默認 32768)個 ID,極大減少數據庫往返。
適用場景:極高併發寫入、跨數據庫遷移但不想用 UUID。現代架構較少直接使用,多被封裝在分布式 ID 生成器(Snowflake、Leaf)中。
應用層手動 entity.setId(value),Hibernate 不再干預。強烈不推薦用於代理主鍵,僅適用於業務主鍵(如身份證號、訂單號)且業務保證唯一性的場景。
配合 <one-to-one constrained="true"> 使用,從表主鍵同時作為外鍵指向主表主鍵。典型場景:用戶表 User 与擴展信息表 UserProfile 共享 ID。
uuid.hex 或 Snowflake 類分布式 ID。identity(簡單高效)。sequence(配合 allocationSize=50~100)。native(最省心)。assigned(但建議重構為代理鍵)。identity 在極高併發下可能引發表級鎖/頁鎖爭用(MySQL 8.0+ 已優化)。sequence 配合 CACHE 參數可大幅降低序列獲取開銷。UUID_TO_BIN/BIN_TO_UUID (MySQL 8.0) 或有序 UUID(COMB)優化。總結:沒有銀彈,只有場景最優解。理解各策略底層機制,結合數據庫特性、併發量、遷移需求、團隊技術棧綜合決策,才是架構師的正確姿勢。