2012-09-25 109 views
1

我希望有人能澄清以下之情況我。hibernate如何處理碰撞?

據我瞭解,當您從休眠請求「行」,例如:

User user = UserDao.get(1); 

我知道有內存ID = 1的用戶。

在web應用中,如果2個網頁請求並加載用戶在同一時間,然後這兩個更新屬性的用戶對象上,會有什麼happend?例如: -

user.pageViews += 1; // the value is current 10 before the increment 
UserDao.update(user); 

這是否會使用在內存中的值(兩個請求具有值10),還是會在數據庫中使用的價值?

回答

2

您必須使用兩個休眠會話的兩個用戶。這意味着內存中有兩個對象實例。如果只使用一個hibernate會話(並且在內存中使用一個對象實例),那麼結果是不可預知的。

在併發更新所述第二更新獲勝的情況下。第一次更新的值被第二次更新覆蓋。爲了避免您通常使用的版本列的第一個更新的損失(見休眠DOC),然後第二次更新變得可以捕獲並在其上有一個錯誤消息作出反應(例如一個「您的紀錄被修改「請允許第二個用戶在修改的記錄上重做他的修改,以確保他的修改不會丟失。」

在頁面視圖計數器的情況下,就像在您的示例中一樣,解決方案,您可以寫一個synchronized方法,其順序計算的頁面訪問量。

1

默認情況下,in memory值用於更新。

在後續我假設你想實現一個自動頁面查看計數器,而不是在網頁界面中修改User。如果你想要這個看看Hibernate的樂觀鎖

Session session = ... 
Transaction tx = ... 

session.lock(user, LockMode.UPGRADE); 
user.increasePageViews(); 

tx.commit(); 
session.close(); 

LockMode.UPGRADE將翻譯在:

因此,計數網頁瀏覽時,假如你需要100%的準確率,你可以在你修改自己的pageView值,以獲得在錶行的排他性鎖定User實體一個SELECT ... FOR UPDATE在您的數據庫中,所以要小心保持儘可能少的鎖,以不影響應用程序的可伸縮性。