2014-01-09 127 views
4

我正在通過Hibernate文檔遇到了LockModes。這些與我們用於數據庫的Isolation levels相同嗎?它們與Isolation levels有什麼不同?休眠鎖定模式/鎖定選項

我正在嘗試一個簡單的例子,並且觀察到,當我使用session.load()方法本身而不是在調用加載對象上的某些方法時敲擊數據庫時,hibernate正在敲擊數據庫。

session.beginTransaction(); //Line 1 
DomesticCat d1 = (DomesticCat)session.load(DomesticCat.class, 1L,LockOptions.UPGRADE); //Line 2 
d1.meow(); //Line 3 
session.getTransaction().commit(); //Line 4 

我發現hibernate在第2行本身遇到數據庫,請告訴我爲什麼會發生這種情況?如果我刪除LockOptions參數,那麼DB命中上的Line 3代替Line 2

API for LockOptions給出了非常小的細節,他們都做了什麼:

READ代表LockMode.READ(超時+範圍不適用)

這是什麼意思timeout + scope do not apply

升級表明LockMode.UPGRADE(永遠等待鎖和虛假的意義 範圍只有實體鎖定)

當我們要使用升級?這是什麼意思scope of false meaning only entity is locked

可能這些是有經驗的人的基本問題,請幫助我理解這裏的概念。

感謝您尋找我的文章。

回答

15

隔離級別會影響您看到的內容。

鎖定模式會影響您允許執行的操作。

hibernate的正常設置是讀提交隔離和樂觀鎖。

通過樂觀鎖定,當兩個人試圖同時編輯相同的數據時,第二個提交會得到一個異常。

  1. 用戶1加載沒有升級鎖定的DomesticCat#1066。
  2. 用戶2加載沒有升級鎖定的DomesticCat#1066。
  3. 用戶2更改貓的名字並提交。
  4. 用戶1更改貓的生日,嘗試提交,拋出異常。

如果使用悲觀鎖,則通過選擇LockMode UPGRADE,然後不允許其他人更改數據,直到請求鎖定UPGRADE的人將其釋放。

  1. 用戶1加載DomesticCat#1066 升級鎖定。
  2. 用戶2加載沒有升級鎖定的DomesticCat#1066。
  3. 用戶2更改貓的名字並嘗試提交。在用戶1釋放鎖定之前,不允許執行此操作,因此數據庫塊和用戶2的會話將處於等待狀態。
  4. 用戶1更改貓的生日,提交。
  5. 用戶2的更新現在可以嘗試提交,但由於他們現在使用樂觀鎖定,他們將會是看到異常的人。

究其原因,查詢必須儘快執行,您,當您升級加載的是,它使用了select ... for update聲明和休眠承諾你,你將有鎖時方法返回,所以它必須執行立即執行該聲明。當你不需要保持鎖定時,hibernate可以是懶惰的,並推遲加載數據,直到你顯示你確實需要它。

通常情況下,當你有一個操作,即必須完成時,無論其他人在做什麼,都要升級鎖定級別。例如,當它是用戶時,你可以向他們顯示錯誤,他們可以調整他們的工作,然後再試一次。但是,如果更新是由消息服務器或後臺進程完成的,處理異常並再次嘗試可能會非常複雜,所以最好鎖定記錄以確保更新能夠進行。

+0

謝謝很多詳細,簡單,非常明確的解釋。 – Chaitanya

+0

你能告訴我什麼是'超時+範圍不適用',另一個'虛假意義的範圍只有實體被鎖定'? – Chaitanya

+1

'timeout'不適用於讀取鎖定,因爲用於實現鎖定的方法沒有被迫等待的風險。範圍不適用於讀鎖,因爲範圍的定義如此。範圍是錯誤的意味着你只能鎖定DomesticCat。如果範圍是真的,那麼您每次鎖定DomesticCat時都會鎖定所有的小貓。這在RDBMS中是危險的,必須小心避免死鎖。 – Affe

1

UPGRADE意味着您要修改加載的對象,並且您不希望任何其他進程在進程中對其進行更改。

在UPGRADE中使用加載是一種奇怪的組合,因爲加載通常只用於引用該對象,以便在修改某個其他對象時可以使用該對象。例如

DomesticCat kitten = (DomesticCat)session.get(DomesticCat.class, 2L); kitten.setParent(d1);

這就是爲什麼如果你使用的負載,Hibernate將只有當你開始引用屬性加載它。