Hibernate 支援樂觀鎖與悲觀鎖解決並發髒資料問題。本文專討樂觀鎖。
自動檢測多事務對同一資料操作,依「先贏」原則提交第一筆事務,後續事務提交時拋出 org.hibernate.StaleObjectStateException。
version),型別限 long, integer, short, timestamp, calendar。<version name="version" column="VERSION" type="integer"/>
Session session1 = sessionFactory.openSession();
Session session2 = sessionFactory.openSession();
MyEntity et1 = session1.load(MyEntity.class, id);
MyEntity et2 = session2.load(MyEntity.class, id);
// et1.version == et2.version (假設 = 1)
Transaction tx1 = session1.beginTransaction();
et1.setName("Entity1");
tx1.commit(); // 版本變為 2
session1.close();
Transaction tx2 = session2.beginTransaction();
et2.setName("Entity2");
tx2.commit(); // 拋出 StaleObjectStateException,因 et2.version=1 < 2
session2.close();
事務 1 提交後資料庫 version 遞增。事務 2 提交時 Hibernate 比對實體中的版本號與資料庫當前版本,若較舊則視為過期資料拋出異常。
在 Web 應用中,更新資料時必須確保實體的 version 欄位為更新前的正確值,否則樂觀鎖機制無法正確判斷。常見問題:
解決:在表單加入 <input type="hidden" name="version" value="${entity.version}"/>,或使用 @Version 註解配合自動版本管理。