[英]How to delete entities in (multithreaded) transactional Spring/JPA
假設有一個服務組件,它使用Book
實體的CrudRepository
。 假設服務的一種方法應該是事務性的,並且(除其他事項外)應使用事務性語義從數據庫中刪除一個實體(即,如果刪除無法執行,則所有結果應回滾)。
大致,
@Component
public class TraService {
@Autowired
BookRepo repo;
@Transactional
public void removeLongest() {
//some repo.find's and business logic --> Book toDel
repo.delete(toDel);
}
}
現在,這應該在多線程上下文中工作,例如在Spring MVC中。 為簡單起見,我啟動了2個線程,每個線程都在一個任務上提供了對TraService
bean的引用。 日志顯示,確實創建了兩個EntityManager
並將它們綁定到相應的線程。 但是,由於第一個線程使用delete
成功,其他線程拋出
org.springframework.orm.jpa.JpaOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1;
從那里,我不知道如何恢復(即,我懷疑回滾未完成,並且在調用事務方法之后線程應該執行的代碼將不會執行)。 工人代碼:
public void run() {
service.removeLongest(); //transactional
System.out.println("Code progressing really well " + Thread.currentThread()); //not executed on thread with exception
}
在Spring / JPA中,我們如何正確處理此類事務性delete
?
簡短的答案:樂觀鎖異常的正確行為是Catch the exception and Retry 。
長答案:樂觀鎖定是一種互斥策略,它假定
來自: https : //en.wikipedia.org/wiki/Optimistic_concurrency_control
多個事務可以經常完成而不會互相干擾
樂觀鎖定主要是由於性能而存在,通常使用考慮了每次修改和version
計數器的字段來實現。 如果在事務期間version
計數器發生更改,則意味着正在進行並發修改,並引發異常。
悲觀鎖定將阻止任何可能的並發修改,更易於管理,但性能較差。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.