Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring@Transactional隔离传播_Java_Spring_Spring Boot_Spring Data Jpa_Transactional - Fatal编程技术网

Java Spring@Transactional隔离传播

Java Spring@Transactional隔离传播,java,spring,spring-boot,spring-data-jpa,transactional,Java,Spring,Spring Boot,Spring Data Jpa,Transactional,是否可以在同一事务之间更改隔离级别 我有一个用例,我希望使用SpringDataJpa的saveAndFlush持久化的未限制数据在不同的事务中可用,或者使内部事务提交数据,但在外部事务中出现任何异常时应该能够回滚 这是必要的,因为我想更新资源,并且在锁表中有一个条目,以避免并发更新。数据库中的锁表在更新事务完成之前不会得到更新,因此我希望将数据提交到锁表,同时在更新操作期间出现任何异常时应回滚。 具有@Transactional的Service1方法将调用Service2的方法。Service

是否可以在同一事务之间更改隔离级别

我有一个用例,我希望使用SpringDataJpa的saveAndFlush持久化的未限制数据在不同的事务中可用,或者使内部事务提交数据,但在外部事务中出现任何异常时应该能够回滚

这是必要的,因为我想更新资源,并且在锁表中有一个条目,以避免并发更新。数据库中的锁表在更新事务完成之前不会得到更新,因此我希望将数据提交到锁表,同时在更新操作期间出现任何异常时应回滚。

  • 具有@Transactional的Service1方法将调用Service2的方法。Service2有@Transactional(隔离=隔离.READ\u UNCOMMITTED),它将调用存储库
  • READ_Uncommitted的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>{
    }
    
    @服务
    类别服务1{
    @自动连线
    服务2服务2;
    @交易的
    公共无效方法1(){
    Foo-Foo=新的Foo();
    foo.setId(“f123”);
    服务2.保存值(foo);
    }
    }
    @服务
    @事务性(隔离=隔离。读取\未提交)
    类别服务2{
    @自动连线
    食物知识库;
    公共void保存值(Foo值){
    fooRepository.saveAndFlush(值);
    }
    }
    公共接口FooRepository扩展了JpaRepository{
    }
    
    情景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>{
    }
    
    @服务
    类别服务1{
    @自动连线
    服务2服务2;
    @交易的
    公共无效方法1(){
    Foo-Foo=新的Foo();
    foo.setId(“f123”);
    服务2.保存值(foo);
    试一试{
    更新操作()
    }catch(Throwable e){//Spring@Transactional是否会在错误时恢复,默认情况下会在RuntimeException和Exception时回滚(在我们明确提到的情况下)?
    service2.deleteByFooId(foo.getId());
    投掷e;
    }
    }
    私有void updateOperation(){
    /*资源*/的更新逻辑-不是数据库更新
    }
    @服务
    @事务性(传播=传播。需要\u新建)
    类别服务2{
    @自动连线
    食物知识库;
    公共void保存值(Foo值){
    fooRepository.saveAndFlush(值);
    }
    公共无效删除(字符串id){
    deleteByFooId(id);
    }
    }
    公共接口FooRepository扩展了JpaRepository{
    }
    
  • 让Thread1启动TX1,Thread2启动TX2
  • 如果TX1已执行saveAndFlush但尚未提交给DB(因为TX1尚未完成),TX2能否访问未限制的数据

  • 如果事务启动后无法更改隔离
  • 是否有一种使用传播或隔离(或任何其他方式)的方法,使用这种方法可以单独提交内部事务,但也可以在外部事务中出现任何异常时回滚

    传播\u需要\u新的Service2方法-将提交数据,但如果Service1中出现任何异常,它将不会回滚

    嵌套在Service2方法上的传播\u-仅当Service1 tx将提交时才会提交数据

    有没有办法实现顶部以粗体突出显示的用例

  • 我现在尝试的解决方案是,在更新时必须处理任何异常,然后手动还原DB锁操作。如果我们需要跟踪多个DB提交并还原相同的DB锁操作,这将非常繁琐。有关伪代码,请参阅场景2

  • 场景2 in..Propagation Require_New..是我使用的。如果在父方法期间出现任何运行时异常,我已在try catch中处理该异常,并还原了锁,该锁作为新事务的一部分在数据库中更新,并在catch块中抛出相同的异常,以便还原父事务也是


    如果您有许多dB状态需要单独还原,那么这种方法将很困难,但现在已经足够了。我使用的场景2 in..Propagation Require_New..是in..Propagation Require_New..。如果在父方法期间出现任何运行时异常,我已在try catch中处理该异常,并还原了upd锁作为新事务的一部分,在DB中初始化,并在catch块中引发相同的异常,以便父事务也被还原


    如果您有许多dB状态需要单独恢复,那么这种方法将很困难,但现在就足够了。

    不,您不能更改正在运行的事务的隔离级别。@M.Deinum-感谢您的快速响应,请检查我的更新,并为我的使用案例提出任何解决方案(一次线程touc以粗体突出显示)他完全忽略了@Transactional,internal@Transactionals。不,您不能更改正在运行的事务的隔离级别。@M.Deinum-感谢您的快速响应,您能检查我的更新并为我的使用案例提出任何解决方案吗?一旦线程触及@Transactional,internal@Transactionals被忽略完全。