原创

Spring事务传播级别理解

温馨提示:
本文最后更新于 2023年04月11日,已超过 774 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我
  • REQUIRED: 默认事务传播级别,如果当前没有事务,就新建一个事务,如果当前存在事务,就加入这个事务

    • 内外为同一个事务,外部回滚内部也回滚,内部回滚外部也回滚

    • public void testMain(){
          A(a1);  //调用A入参a1
          testB();    //调用testB
      }
      @Transactional(propagation = Propagation.REQUIRED)
      public void testB(){
          B(b1);  //调用B入参b1
          throw Exception;     //发生异常抛出
          B(b2);  //调用B入参b2
      }
      

      上面a1会存入,b1b2会回滚,因为testB没有事务就新建一个事务

  • SUPPORTS:当前存在事务则加入当前事务,如果当前没有事务,就以非事务方法执行

    • public void testMain(){
          A(a1);  //调用A入参a1
          testB();    //调用testB
      }
      @Transactional(propagation = Propagation.SUPPORTS)
      public void testB(){
          B(b1);  //调用B入参b1
          throw Exception;     //发生异常抛出
          B(b2);  //调用B入参b2
      }
      

      这种情况下a1、b1、会存入,b2不会存,因为调用方testmain没有开启事务,testb是SUPPORTS,即以非事务方法执行

  • MANDATORY:当前存在事务则加入当前事务,如果当前没有事务,就抛出异常

    • public void testMain(){
          A(a1);  //调用A入参a1
          testB();    //调用testB
      }
      @Transactional(propagation = Propagation.MANDATORY)
      public void testB(){
          B(b1);  //调用B入参b1
          throw Exception;     //发生异常抛出
          B(b2);  //调用B入参b2
      }
      

      a1会存储,b1b2不会存储,之所以b1没有存储的是因为MANDATORY只要是非事务就会抛出异常,还没走到b1就报错了,如果testmain设置了required的话就会以事务方式运行,可以正常回滚

  • REQUIRES_NEW: 创建一个新事务,如果当前存在事务,则挂起该事务

    • @Transactional(propagation = Propagation.REQUIRED)
      public void testMain(){
          A(a1);  //调用A入参a1
          testB();    //调用testB
          throw Exception;     //发生异常抛出
      }
      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public void testB(){
          B(b1);  //调用B入参b1
          B(b2);  //调用B入参b2
      }
      

      上面a1会回滚,b1b2不会回滚,因为开启了新的事务,即外部回滚内部不回滚,内部回滚外部不回滚

  • NOT_SUPPORTED:始终以非事务方式执行,如果当前存在事务,则挂起当前事务

    • @Transactional(propagation = Propagation.REQUIRED)
      public void testMain(){
          A(a1);  //调用A入参a1
          testB();    //调用testB
      }
      @Transactional(propagation = Propagation.NOT_SUPPORTED)
      public void testB(){
          B(b1);  //调用B入参b1
          throw Exception;     //发生异常抛出
          B(b2);  //调用B入参b2
      }
      

      a1b2不会存储,b1会存储,因为testb没有事务,当b1执行完后抛出异常会导致testmain回滚,导致a1也不会存储

  • NEVER:不使用事务,如果当前事务存在则抛出异常

    • @Transactional(propagation = Propagation.REQUIRED)
      public void testMain(){
          A(a1);  //调用A入参a1
          testB();    //调用testB
      }
      @Transactional(propagation = Propagation.NEVER)
      public void testB(){
          B(b1);  //调用B入参b1
          B(b2);  //调用B入参b2
      }
      

      上面a1b1b2都不会存储,因为testb会抛出异常导致testmain回滚

  • NESTED:如果当前存在事务,则在嵌套事务中执行,否则和REQUIRED的操作一样(开启一个事务)

    • @Transactional(propagation = Propagation.REQUIRED)
      public void testMain(){
          A(a1);  //调用A入参a1
          testB();    //调用testB
          throw Exception;     //发生异常抛出
      }
      @Transactional(propagation = Propagation.NESTED)
      public void testB(){
          B(b1);  //调用B入参b1
          B(b2);  //调用B入参b2
      }
      

      上面都不会存储,因为testb子事务会跟着testmain父事务的回滚而回滚

    • @Transactional(propagation = Propagation.REQUIRED)
      public void testMain(){
          A(a1);  //调用A入参a1
          try{
              testB();    //调用testB
          }catch(Exception e){
      
          }
          A(a2);
      }
      @Transactional(propagation = Propagation.NESTED)
      public void testB(){
          B(b1);  //调用B入参b1
          throw Exception;     //发生异常抛出
          B(b2);  //调用B入参b2
      }
      

      a1a2会存储,b1b2会回滚,因为父事务catch了异常所以只有子事务回滚了,如果这里的testb传播级别是REQUIRED的话都不会存储,因为是在同一个事务中

正文到此结束