2 回答

TA貢獻1871條經驗 獲得超8個贊
您遇到的更新被稱為丟失更新,這真的不是JPA級的問題,您可以在MySQL shell中輕松重現此問題。我假設您沒有在數據庫本身中進行任何更改,因此您的默認事務隔離級別是 。REPEATABLE READ
在MySQL中,不會檢測到可能的丟失更新(即使這是此隔離級別的常見理解)。您可以在SO和評論線程上查看此答案以了解更多信息。REPEATABLE READ
基本上,通過使用MVCC,MySQL試圖避免爭用和死鎖。在你的情況下,你將不得不做出權衡,并選擇為了一致性而犧牲一些速度。
您可以選擇使用語句或設置更嚴格的隔離級別,即(您可以對單個事務執行此操作)。這兩個選項都將阻止讀取,直到并發事務提交/回滾。因此,您將在稍晚一點(或更晚,具體取決于應用程序的要求)看到數據的一致視圖。SELECT ... FOR UPDATE
SERIALIZABLE
并發性很難。:)
更新:在考慮了下面的評論之后,您實際上還有另一種選擇:為數據模型實現樂觀鎖定。JPA對此有支持,請看這里和這里。您實現的目標基本上是相同的,但是使用稍微不同的方法(您將不得不重新啟動未能不匹配版本的事務),并且由于鎖定較少,因此爭用較少。

TA貢獻1818條經驗 獲得超7個贊
我認為您面臨的問題是,FK 關系的屬性鎖定由關系的擁有方控制。
由于集合是用它注釋的,因此它不會控制鎖,因此另一端會這樣做,這意味著在更新集合時,您將獲得兩個單獨的鎖,它們實際上并不能相互識別。book_reads
@OneToMany(mappedBy = "reader")
刪除和注釋應該可以解決這個問題。Book_read.reader
mappedBy
所有這些實際上都適用于具有版本屬性的樂觀鎖定,這是無論如何都要執行操作的推薦方法。
另請參閱Vlad Mihalcea關于該主題的文章:https://vladmihalcea.com/hibernate-collections-optimistic-locking/
添加回答
舉報