Spring Data JPA 事務鎖


1.概述

在本快速教程中,我們將討論在Spring Data JPA中為自定義查詢方法和預定義存儲庫的CRUD方法啟用事務鎖, 我們還將查看不同的鎖類型並設置事務鎖超時。

2.鎖類型

JPA定義了兩種主要的鎖類型,即悲觀鎖和樂觀鎖。

2.1悲觀鎖

當我們在事務中使用悲觀鎖並訪問實體時,它將立即鎖定。通過提交或回滾事務來釋放鎖。

2.2樂觀鎖

在樂觀中,事務不會立即鎖定實體。相反,事務通常會保存實體的狀態,並為其分配版本號。

當我們嘗試在不同的事務中更新實體的狀態時,事務會在更新期間將保存的版本號與現有的版本號進行比較。

此時,如果版本號不同,則表示無法修改實體。如果存在活動事務,那么該事務將被回滾,並且底層JPA實現將拋出OptimisticLockException

除版本號方法外,我們還可以使用其他方法,如時間戳,哈希值計算或序列化校驗和,具體取決於哪種方法最適合我們當前的開發環境。

3.在查詢方法上啟用事務鎖

要獲取實體的鎖定,我們可以通過使用@Lock來注解目標查詢方法, 並傳遞所需的鎖定模式類型

鎖定模式類型(Lock mode types)是鎖定實體時要指定的枚舉值。然后,將指定的鎖定模式傳遞到數據庫,以在實體對象上應用相應的鎖定。

要在Spring Data JPA存儲庫的自定義查詢方法上指定鎖定,我們可以使用@Lock注解該方法並指定所需的鎖定模式類型:

@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("SELECT c FROM Customer c WHERE c.orgId = ?1")
public List<Customer> fetchCustomersByOrgId(Long orgId);

要強制鎖定預定義的存儲庫方法(如findAll或findById(id)),我們必須在存儲庫中聲明方法並使用@Lock注解該方法:

@Lock(LockModeType.PESSIMISTIC_READ)
public Optional<Customer> findById(Long customerId);

當顯式啟用鎖並且沒有活動事務時,底層JPA實現將拋出TransactionRequiredException

如果無法授予鎖並且鎖沖突不會導致事務回滾,則JPA會拋出LockTimeoutException。但它不標記回滾的活動事務。

4.設置事務鎖定超時

使用悲觀鎖時,數據庫將嘗試立即鎖定實體。當無法立即獲取鎖定時,底層JPA實現會拋出LockTimeoutException。為避免此類異常,我們可以指定鎖超時時間。

在Spring Data JPA中,可以使用@QueryHints指定鎖定超時時間:

@Lock(LockModeType.PESSIMISTIC_READ)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "3000")})
public Optional<Customer> findById(Long customerId);

有關在不同范圍設置鎖定超時提示的更多詳細信息,請參見ObjectDB文章

5.結論

在本教程中,我們學習了不同類型的事務鎖定模式,以及如何在Spring Data JPA中啟用事務鎖,並簡單介紹了如何設置鎖定超時。

在正確的位置應用正確的事務鎖,可以幫助維護高並發情況下應用程序中數據完整性。

當交易需要嚴格遵守ACID規則時,我們應該使用悲觀鎖。當我們需要允許多個並發讀取以及在應用程序上下文中可接受的最終一致性時,應該應用樂觀鎖。

當然,可以在Github上找到悲觀鎖和樂觀鎖的示例代碼。

原文:https://www.baeldung.com/java-jpa-transaction-locks

作者:baeldung

譯者:Leesen


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM