首页 文章

Spring @Transactional隔离传播

提问于
浏览
0

可以在相同事务之间更改隔离级别

我有一个用例,我想要使用SpringDataJpa的saveAndFlush持久化的未提交数据在不同的事务中可用或者 make the Inner Transaction commit the data but should be able to rollback in case of any exception in the outer transaction

This is needed as I want to update a resource and would have an entry in lock table to avoid concurrent updates. The lock table in DB is not getting updated untill the Update transaction is getting completed , hence I want to commit the data to lock table and at the same time should rollback in case of any exceptions during update operation.

  • 具有@Transactional的Service1方法将调用Service2的方法 . Service2有@Transactional(隔离= Isolation.READ_UNCOMMITTED),后者又会调用存储库 .

READ_UNCOMMITED的Service2隔离是优先还是默认?

隔离中的此更改是否反映在从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但尚未提交给DB(因为TX1尚未完成),TX2是否可以访问未提交的数据?

  • 如果启动事务,则无法更改隔离

有没有办法使用传播或隔离(或任何其他方法)使用哪个内部事务可以单独提交,但也可以在外部事务中的任何异常情况下回滚?

Service2方法上的PROPAGATION_REQUIRES_NEW - 将提交数据但是如果Service1中出现任何异常,它将不会回滚

Service2方法的PROPAGATION_NESTED - 仅在Service1 tx提交时才提交数据

有没有办法在顶部实现BOLD中突出显示的用例?

  • 我现在尝试的解决方案是在更新时必须处理任何异常,然后手动恢复数据库锁定操作 . 如果我们需要跟踪许多数据库提交并恢复相同,这是很乏味的 . 对于伪代码,请参阅Scenario2

1 回答

  • 0

    方案2在..Propagation Require_New ..是我用过的 . 如果在父方法期间出现任何运行时异常,我在try catch中处理了该异常并恢复了作为新事务的一部分在DB中更新的锁,并在catch块中抛出了相同的异常,以便父事务被还原太 .

    如果您有多个dB状态要单独还原,这种方法将很困难,但现在就足够了

相关问题