專案從 Hibernate 3.1 升級至 3.2 後,原本正常的 <generator class="identity"/> 主鍵生成策略拋出 MappingException: Dialect does not support identity key generation。本文記錄排查過程、根本原因與解決方案。
Exception in thread "main" net.sf.hibernate.MappingException:
Dialect does not support identity key generation
at net.sf.hibernate.dialect.Dialect.getIdentitySelectString(Dialect.java:305)
at net.sf.hibernate.persister.AbstractEntityPersister.<init>(AbstractEntityPersister.java:646)
at net.sf.hibernate.persister.EntityPersister.<init>(EntityPersister.java:690)
at net.sf.hibernate.persister.PersisterFactory.createClassPersister...
<id name="kid" type="java.lang.Long">
<column name="KID" precision="22" scale="0"/>
<generator class="identity"/>
</id>
<id name="kid" type="java.lang.Long">
<column name="KID" precision="22" scale="0"/>
<generator class="increment"/>
</id>
修改後程式正常運行。
| 策略 | 適用資料庫 | 說明 |
|---|---|---|
increment | 所有 (單進程) | Hibernate 內存計數器,最大值+1,**不適用叢集/多進程** |
identity | MySQL、SQL Server、Sybase、DB2、PostgreSQL | 資料庫自增欄位 (AUTO_INCREMENT/IDENTITY) |
sequence | Oracle、DB2、PostgreSQL | 資料庫 Sequence 物件 |
hilo | 支援 Sequence 的資料庫 | 高低位算法,減少資料庫往返 |
native | 跨資料庫移植 | 自動選擇 identity/sequence/hilo |
uuid | 所有 | UUID 字串,無序、唯一 |
assigned | 所有 | 應用程式手動指定 |
Dialect.getIdentitySelectString() 若回傳 null 則直接拋 MappingExceptionidentityidentity (或 native)identity (支援 IDENTITY 欄位) 或 sequencesequence (需建立 Sequence 物件)native (自動適配)increment (效能最好,但**嚴禁叢集**).hbm.xml 中的 <generator> 設定hibernate.dialect=org.hibernate.dialect.Oracle10gDialect 等increment 看似通用但**極度危險** (叢集下主鍵衝突),僅限單機開發測試native 或明確指定資料庫支援的策略