JPA实体锁定模式的差异
JPA本質(zhì)上提供了兩種鎖定機制,以幫助同步對實體的訪問。 兩種機制都可以防止以下情況:兩個事務(wù)在不知道的情況下相互覆蓋數(shù)據(jù)。
通過實體鎖定,我們通常希望通過2個并行事務(wù)來防止以下情況:
結(jié)果,亞當(dāng)所做的更改完全被芭芭拉(Barbara)所取代,甚至沒有引起她的注意。 像這樣的場景有時被稱為臟讀 。 顯然,理想的結(jié)果是Adam編寫XA,而Barbara被迫在編寫XB之前檢查XA更改。
樂觀鎖的工作原理
樂觀鎖定基于這樣的假設(shè):沖突非常少見;如果發(fā)生沖突,則拋出錯誤是可以接受的,并且比防止沖突更方便。 允許其中一項交易正確完成,但其他任何交易都會例外回滾,并且必須重新執(zhí)行或丟棄。
通過樂觀鎖定,亞當(dāng)和芭芭拉可能出現(xiàn)以下情況:
如您所見,芭芭拉被迫審查亞當(dāng)?shù)母?#xff0c;如果她決定,她可能會修改亞當(dāng)?shù)母牟⒈4?#xff08;合并更改)。 最終數(shù)據(jù)包含亞當(dāng)和巴巴拉的變化。
JPA完全控制樂觀鎖定。 它需要數(shù)據(jù)庫表中的其他版本列。 它完全獨立于用于存儲關(guān)系數(shù)據(jù)的基礎(chǔ)數(shù)據(jù)庫引擎。
悲觀鎖定如何工作
對于某些人來說,悲觀鎖定被認為是很自然的。 當(dāng)事務(wù)需要修改實體(可以由另一個事務(wù)并行修改)時,事務(wù)將發(fā)出鎖定該實體的命令。 所有鎖將保留到事務(wù)結(jié)束,然后自動釋放。
使用悲觀鎖,情況可能是這樣的:
如我們所見,Barbara再次被迫編寫XAB,其中也包含Adam所做的更改。 但是,該解決方案與樂觀方案完全不同–芭芭拉需要等待亞當(dāng)?shù)慕灰淄瓿珊蟛拍茏x取數(shù)據(jù)。 此外,我們需要在兩個事務(wù)中手動發(fā)出鎖定命令,以使該方案起作用。 (由于我們不確定亞當(dāng)或芭芭拉首先要處理哪個事務(wù),因此兩個事務(wù)都需要在修改數(shù)據(jù)之前先鎖定數(shù)據(jù)。)樂觀鎖定比悲觀鎖定需要更多的設(shè)置,每個實體都需要使用version列,但隨后我們不需要記住在交易中發(fā)出鎖。 JPA自動執(zhí)行所有檢查,我們只需要處理可能的異常。
悲觀鎖定使用基礎(chǔ)數(shù)據(jù)庫提供的鎖定機制鎖定表中的現(xiàn)有記錄。 JPA需要知道如何觸發(fā)這些鎖定,并且某些數(shù)據(jù)庫不完全支持。
甚至JPA規(guī)范都說,不需要提供PESSIMISTIC_READ(因為許多數(shù)據(jù)庫僅支持WRITE鎖):
這是允許的,以使用實施LockModeType.PESSIMISTIC_WRITE其中LockModeType.PESSIMISTIC_READ請求,而不是相反。
JPA中可用鎖類型的列表
首先,我想說的是,如果實體中提供了@Version列,則JPA會默認為此類實體打開樂觀鎖定。 您不需要發(fā)出任何鎖定命令。 但是,您可以隨時使用以下一種鎖類型發(fā)出鎖:
- 這確實是默認設(shè)置。 如ObjectDB所述,通常將其忽略。 在我看來,它只是存在的,這樣您就可以動態(tài)地計算鎖定模式,即使鎖定最終是最優(yōu)的,也可以進一步傳遞它。 雖然用例不是很可能,但是提供一個甚至引用默認值的選項也是一種很好的API設(shè)計。
- 示例:Java LockModeType lockMode = resolveLockMode(); A a = em.find(A.class, 1, lockMode);
- 這是很少使用的選項。 但是,如果您想鎖定另一個實體對這個實體的引用,這可能是合理的。 換句話說,即使您未修改某個實體,您也希望鎖定該實體的工作,但是其他實體也可能相對于該實體而被修改。
- 例:
- 我們有實體書和書架。 可以將Book添加到書架中,但是book沒有對其書架的引用。 鎖定將書移動到書架上的操作是合理的,這樣一本書不會最終出現(xiàn)在兩個書架中。 要鎖定此操作,僅鎖定當(dāng)前書架實體是不夠的,因為書還不必在書架上。 鎖定所有目標(biāo)書架也沒有意義,因為它們在不同交易中可能會有所不同。 唯一有意義的是鎖定書本實體本身,即使在我們這種情況下它沒有被更改(它不保留對其書架的引用)。
- 此模式類似于LockModeType.PESSIMISTIC_WRITE ,但有一點不同:在通過某種事務(wù)在同一實體上施加寫鎖定之前,它不應(yīng)阻止讀取實體。 它還允許其他事務(wù)使用LockModeType.PESSIMISTIC_READ鎖定。 WRITE和READ鎖之間的區(qū)別在這里(ObjectDB)和這里(OpenJPA)都有很好的解釋。 但是,由于規(guī)范允許,很多情況下,它的行為類似于LockModeType.PESSIMISTIC_WRITE ,許多提供程序并未單獨實現(xiàn)它。
- 這是LockModeType.PESSIMISTIC_READ的增強版本。 有了WRITE鎖定后,JPA借助數(shù)據(jù)庫將阻止任何其他事務(wù)讀取該實體,而不僅僅是像READ鎖定那樣進行寫入。
- 這是另一種很少使用的鎖定模式。 但是,這是您需要結(jié)合PESSIMISTIC和OPTIMISTIC機制的一種選擇。 在以下情況下,使用普通的PESSIMISTIC_WRITE可能會失敗:
- 事務(wù)A使用樂觀鎖定并讀取實體E
- 事務(wù)B獲得對實體E的WRITE鎖定
- 事務(wù)B提交并釋放E的鎖
- 事務(wù)A更新E并提交
為了發(fā)出某種類型的鎖,JPA提供了以下方法:
- 一些EntityManager方法接受一個可選參數(shù)來指定鎖定類型,例如:
- find(類entityClass,Object primaryKey,LockModeType lockMode)
- 查詢還提供setLockMode(LockModeType lockMode)方法來鎖定將由查詢檢索的所有實體
您可以在JPA中使用兩種類型的鎖定機制中的任何一種。 如果您使用類型PESSIMISTIC_FORCE_INCREMENT悲觀鎖,也可以在必要時將它們混合使用。
- 要了解更多信息,請閱讀Vlad Mihalcea的優(yōu)秀博客。
翻譯自: https://www.javacodegeeks.com/2016/02/differences-jpa-entity-locking-modes.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的JPA实体锁定模式的差异的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信注销账号
- 下一篇: jcmd:一个可以全部统治的JDK命令行