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

Hibernate Generator 坑點:increment 與 identity 需搭配 Long 型別主鍵

     編輯:Java 相關知識

問題背景

環境:Tomcat 5.5 + Struts + Hibernate 2.1 + jTDS JDBC + SQL Server 2000

嘗試 1:native 策略 → FOR UPDATE 語法錯誤

[ERROR] TableGenerator - could not read a hi value
java.sql.SQLException: 第 1 行: FOR UPDATE 子句僅允許用於 DECLARE CURSOR。

native 讓 Hibernate 自動選擇策略,SQL Server 下退回 TableGenerator (Hi/Lo 演算法),產生 SELECT ... FOR UPDATE 鎖定資料列,但 jTDS 驅動不支援此語法。

嘗試 2:identity 策略 → 型別不符 (Long vs Integer)

[ERROR] ReflectHelper - IllegalArgumentException in class: User, setter method of property: userid
expected type: java.lang.Integer, actual value: java.lang.Long

SQL Server IDENTITY 欄位回傳 java.lang.Long,但實體類別主鍵定義為 Integer,導致設值失敗。

嘗試 3:increment 策略 → 同樣型別不符

increment 由 Hibernate 在記憶體中遞增,內部邏輯同樣產生 Long 值,同樣報錯。

解決方案:主鍵型別改為 Long

1. 實體類別修改

// 修改前
private Integer userid;
// 修改後
private Long userid;

2. 映射檔修改

<id column="userid" name="userid" type="long">
    <generator class="increment"/>  <!-- 或 identity -->
</id>

3. 結果

執行成功,increment 與 identity 皆正常運作。

深度分析:為什麼必須是 Long?

  • Hibernate 內部識別碼產生器 (IdentifierGenerator) 介面回傳 Serializable,具體實作多以 Long 為基礎型別
  • SQL Server IDENTITY 欄位透過 JDBC getGeneratedKeys() 取得時,jTDS 驅動回傳 Long
  • increment 策略的 IncrementGenerator 內部計數器為 long,生成 Long 物件
  • 結論: 使用資料庫原生自增或 Hibernate 記憶體自增策略時,主鍵 Java 型別建議統一用 Long (或 long),避免型別轉換失敗

最佳實務建議

  1. 新專案主鍵預設使用 Long,相容性最佳
  2. SQL Server 建議用 identity (資料庫層面保證唯一),搭配 generator class="identity"
  3. 若需跨資料庫移植,native 配合 Long 主鍵是較安全選擇 (需驅動支援 FOR UPDATE 或替代鎖定機制)
  4. 避免使用 increment 於叢集環境 (記憶體計數器不同步會產生重複鍵值)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved