关于Spring的隔离级别和传播

下面代码中,我想要先在f1中从表table_apple读一些记录,然后在f2中更新table_apple其中某些记录,然后在f1中从表table_apple读出f2更新后的记录,所以要用Isolation.READ_COMMITTED覆盖掉mysql默认的REPEATABLE隔离级别
另外又不想让f1()抛异常导致f2被回滚,所以用propogation= Propogation.REQUIRES_NEW

 @Transactional(isolation= Isolation.READ_COMMITTED)
 void f1(){
      select from table_apple;
      f2();
      select from table_apple;
      throw new RuntimeException()
 }
 
 
 @Transactional(propogation= Propogation.REQUIRES_NEW, isolation= Isolation.REPEATABLE_READ)
 void f2(){
      update table_apple;
 }
 
 

我想问的是,我这样用会达到目标吗?另外,我在f2中显示写出了isolation= Isolation.REPEATABLE_READ,事实上默认就是这个级别,所以写不写一样,我想问的是,假如内层方法没有用propogation= Propogation.REQUIRES_NEW,则和外层方法属于同一个事务,但是如果标注了不同的隔离级别,那么是外层方法的隔离级别覆盖所有内层方法@Transactional上标注的隔离级别吗?


补充,看了@znydev的回答,我疏忽了,我要问的是假如两个方法在不同的类中或者f1用所在类代理类调用f2

阅读 2.1k
1 个回答

看你上面的问题,下面的回答有个前提,就是 f1 和 f2 在同一个类里面

首先回答一下主要问题,你这样做不能达到目标,这些操作会在同一个事务中进行,而不是 f2 新开一个事务

简单说下原因:Spring 的事务使用的 AOP 实现的,你这样做的代码,可以看成下面的形式


class Demo { 
    @Transactional(isolation= Isolation.READ_COMMITTED)
    void f1(){
        select from table_apple;
        this.f2();
        select from table_apple;
        throw new RuntimeException()
    }
 
 
    @Transactional(propogation= Propogation.REQUIRES_NEW)
    void f2(){
      update table_apple;
    }
}

其中 如果 f1 调用 f2 使用的是 this 而不是代理类,所以 f2 只是一个普通方法,事务注解并不会生效,你可以将这两个方法放在两个类中,如


class Demo2 {
     
    @Transactional(propogation= Propogation.REQUIRES_NEW)
    void f2(){
      update table_apple;
    }
}

class Demo {

    private Demo2 demo2;
 
    @Transactional(isolation= Isolation.READ_COMMITTED)
    void f1(){
        select from table_apple;
        demo2.f2();
        select from table_apple;
        throw new RuntimeException()
    }

}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题