繁体   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