是否可以在同一事务中更改隔离级别?
我有一个用例,希望使用SpringDataJpa的saveAndFlush持久化的未提交数据可以在不同的事务中使用,或者使内部事务提交数据,但在外部事务发生任何异常时应该能够回滚。
这是必需的,因为我想要更新资源,并在锁定表中具有条目以避免并发更新。数据库中的锁表在更新事务完成之前没有得到更新,因此我想要将数据提交到锁表,并在更新操作期间出现任何异常的情况下回滚。
- Service1方法具有@Transactional注解,将调用Service2的方法。 Service2具有@Transactional(isolation = Isolation.READ_UNCOMMITTED),然后会调用存储库。
Service2的READ_UNCOMMITED隔离级别会优先还是默认隔离级别?
更改隔离级别是否会反映在从Service1传播的同一事务中?
场景1:
@Service
class Service1{
@Autowired
Service2 service2;
@Transactional
public void method1(){
Foo foo=new Foo();
foo.setId("f123");
service2.saveValue(foo);
}
}
@Service
@Transactional(isolation=Isolation.READ_UNCOMMITTED)
class Service2{
@Autowired
FooRepository fooRepository;
public void saveValue(Foo value){
fooRepository.saveAndFlush(value);
}
}
public interface FooRepository extends JpaRepository<Foo, String>{
}
场景2:
@Service
class Service1{
@Autowired
Service2 service2;
@Transactional
public void method1(){
Foo foo=new Foo();
foo.setId("f123");
service2.saveValue(foo);
try{
updateOperation()
}catch(Throwable e){ // does Spring @Transactional revert on ERRORS, by default it rollback on RuntimeException and Exception(in case we explicitly mention)?
service2.deleteByFooId(foo.getId());
throw e;
}
}
private void updateOperation(){
/* update logic for resource */- Not a DB update
}
@Service
@Transactional(propagation=Propagation.REQUIRES_NEW)
class Service2{
@Autowired
FooRepository fooRepository;
public void saveValue(Foo value){
fooRepository.saveAndFlush(value);
}
public void delete(String id){
deleteByFooId(id);
}
}
public interface FooRepository extends JpaRepository<Foo, String>{
}
- 让Thread1启动TX1,Thread2启动TX2。
如果TX1已经执行了saveAndFlush但尚未提交到数据库(因为TX1尚未完成),那么TX2能够访问未提交的数据吗?
- 一旦事务启动,隔离级别就无法更改。
是否有一种使用Propagation或Isolation(或其他任何方式)的方法,使内部事务可以单独提交,但在外部事务发生任何异常的情况下也可以回滚?
Service2方法上使用PROPAGATION_REQUIRES_NEW - 将提交数据,但在Service1中出现任何异常时不会回滚
Service2方法上使用PROPAGATION_NESTED - 仅在Service1 tx提交时才会提交数据
是否有任何方法可以实现上述加粗的用例?
- 我现在尝试的解决方案是手动处理更新操作中的任何异常,然后手动回滚DB锁操作。如果我们需要跟踪多个DB提交并撤消它们,这将变得很繁琐。有关伪代码,请参见Scenario2。