spring事务的传播

关于事务的传播,我们先确定一个场景:方法A调用方法B,方法A可能存在事务,也可能不存在事务,我们这里重点关注方法B上定义的事务传播行为,以及方法B中出现异常时,方法A应该如何处理事务的提交或回滚(如果存在)。



    @Autowired private ServiceB serviceB;
    
    public void methodA() {
        // do anything
        serviceB.mehtodB();
        // do anything
    }

    @Transactional(propagation = Propagation.NESTED)
    public void mehtodB() {
        // do anything
    }


事务的传播行为类型

1 .PROPAGATION_REQUIRED(默认实现)

方法B的执行需要有事务,如果方法A有事务,那么方法B加入方法A的事务,方法A或B的异常都会导致整个事务回滚。

2 .PROPAGATION_SUPPORTS

方法B的执行支持事务,如果方法A存在事务,那么方法B加入方法A的事务,否则方法B以无事务的方式执行。此情景下,A方法事务回滚也将导致方法B回滚,方法A无事务则不影响。

3 .PROPAGATION_MANDATORY

方法B强制必须在事务条件下执行,方法B加入方法A的事务执行,如果方法A无事务,则抛出异常。

4 .PROPAGATION_REQUIRES_NEW

方法B必须在新事务中执行,如果A存在事务,那么把方法A的事务挂起;此种情境下,方法A和方法B的回滚不会影响到对方。

5 .PROPAGATION_NOT_SUPPORIED

方法B必须在无事务条件下执行,如果方法A存在事务,那么需要将方法A的事务挂起。

6 .PROPAGATION_NEVER

方法B必须在不存在事务的条件下执行,如果方法A存在事务,则抛出异常。

7 .PROPAGATION_NESTED

这里我们需要了解下嵌套事务的提交

  • 我们把嵌套事务视作一棵树,根节点事务叫做顶层的事务,其它事务是顶层事务的子事务;
  • 任何嵌套的子事务的提交和回滚,都必须在它的父事务提交后进行;嵌套的子事务可以独立于当前事务进行单独地提交或回滚;
  • 任何父事务的回滚都会导致它的所有子事务的回滚。

嵌套事务,如果方法A存在事务,那么方法B的创建一个方法A事务的嵌套事务(从数据库的层面看,也可视为子事务),如果方法A不存在事务,那么行为与PROPAGATION_REQUIRED相同。
此处,父事务的回滚行为会导致子事务回滚;而子事务的回滚和提交独立于父事务。

注意事项

  • 非public 方法会导致事务失效

  • 事务默认的异常类型是: RuntimeException

posted @ 2022-03-27 16:13  bokerr  阅读(53)  评论(0编辑  收藏  举报