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