2011-03-01 67 views
0

我試圖用重試攔截器實現基本的樂觀鎖定機制。在jpa/spring/hibernate中簡單的樂觀鎖問題

所以事情是有一個對象測驗與屬性respondCount。如果在測驗更新期間拋出樂觀的鎖定異常,則將再次從重試攔截器調用相應的更新方法。

的事情是,什麼是不正確的,因爲重試的方法具有相同的版本號號每一次,正因爲如此它會不管失敗的交易。

版本:10

過程答: 開始更新測驗,10個 過程B: 開始更新測驗,10版 過程B: 完成更新測驗,11版 過程答: 樂觀例外拋出提出更新競猜,重試進程A 重試的方法中的版本始終爲10

我能做些什麼呢?它應該爲了增加自動版本,以成功交易

回答

1

樂觀鎖定異常是這樣處理的:

首先重新讀取記錄,獲取新的版本號和衝突的交易中寫道更新的字段值。

然後根據新值重新應用您的操作。 在你的情況下,這很簡單 - 增加一個值是順序無關的或可交換的。其他操作可能不容易重新應用 - 例如,假設事務都試圖將問題跟蹤器中的錯誤從一個工作流程狀態轉移到另一個工作流程狀態。此轉換隻能發生一次,因此重試事務將需要檢查該轉換的錯誤是否仍然處於有效狀態,如果不存在,則會向用戶報告錯誤。

0

你試圖打敗樂觀鎖:d,這提出了一個問題:你需要樂觀鎖?

我可以看到重試的唯一理智方式就是刷新對象,然後再次應用更改......無論如何,您將覆蓋數據,這與想法不符樂觀鎖。

在你的情況,我想無論是在所有禁用樂觀鎖,或者把計數的輔助表,不樂觀鎖。

+0

計數也需要鎖定的 - 否則兩個客戶端可以讀取「1」,然後寫兩個「2」時,正確的計數爲「3」。 – tgdavies 2011-03-01 21:35:28

1

在我看來,要更新QUIZZ,即使別人已經更新了它在你的背後(這將引發樂觀除外)。如果是這樣的話,爲什麼你在這個實體上啓用樂觀的登錄?只要刪除版本字段,它甚至不會重試。

如果您確實想保留版本字段,請更改該方法以使其從數據庫獲取quizz,將新加載的quizz的版本號複製到分離的實例,然後合併分離的實例以複製所有附加的新值。

+0

我在考慮使用樂觀鎖定的原因是爲了防止例如許多併發用戶在測驗的quizResponsesCount屬性同時進行測驗和增量的情況。現在我正在試驗你的建議:我修改了我的服務層,它只從數據庫中檢索新對象(測驗),然後更新它們。據我測試,它接近重試機制以這種方式工作良好,這意味着它檢測到樂觀鎖定,然後重試該方法,下次會成功。這樣可以嗎? – 2011-03-01 18:08:48