簡體   English   中英

如何在(多線程)事務性Spring / JPA中刪除實體

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM