在我的Web應用程序中,我有幾個線程可能同時訪問相同的數據,爲什麼我決定實現樂觀(版本控制)和悲觀鎖定Hibernate。如何正確鎖定和重新加載實體
目前我使用下面的模式來鎖定一個實體,並在其上執行寫操作(使用彈簧事務管理器和事務劃分@Transactional):
@Transactional
public void doSomething(entity) {
session.lock(entity, LockMode.UPGRADE);
session.refresh(entity);
// I change the entity itself as well as entites in a relationship.
entity.setBar(...);
for(Child childEntity : entity.getChildren()) {
childEntity.setFoo(...);
}
}
但是,有時我得到StaleObjectException
當@事務性衝突告訴我一個ChildEntity已經被同時修改,並且現在有一個錯誤的版本。
我想我是不正確刷新entity
及其子女所以我正在處理陳舊的數據。有人可以指出如何實現這一點?我的一些想法包括清除持久性上下文(會話)或再次調用session.lock(entity, LockMode.READ)
,但我不確定這裏是什麼是正確的。
感謝您的幫助!
我使用MySQL InnoDB,它支持「SELECT ... FOR UPDATE」,所以我在這裏沒有看到問題。此外,爲了在進行併發修改時獲得「通知」,我也利用樂觀鎖定。 – Erik
對不起,錯過了你對孩子有問題的地方(用粗體:))。我已經更新了答案...... – Stas
在我的代碼中,我總是鎖定實體,即使我只想更新實體而不是子代。所以也應該有獲得的鎖。我主要關心的是,我並不僅僅使用刷新工具來處理最新的實體/孩子。 – Erik