Spring声明式事务@Transactional传播行为

propagation = Propagation.REQUIRED

默认的传播行为,该方法需要再事务环境下运行,被调用的方法有事务的话就和它在同一个事务下属于平级那一个异常都会回滚,没有就自己开启新的事务,调用别的没事务的方法会把它加到同一个事务中。下面会给出相应example

调用A方法

 @Transactional(rollbackFor = Exception.class)
    @Override
    public void closeOrderAndReturnStock(InyGroupOrderDo orderDo) {
        InyGroupOrderDo updateGroupOrder = new InyGroupOrderDo();
        updateGroupOrder.setId(569L);
        updateGroupOrder.setStatus(4);
        updateGroupOrder.setActivityId(12L);
        inyGroupOrderDao.updateById(updateGroupOrder);
        InyGroupActivityDo updateGroupActivity=new InyGroupActivityDo();
        updateGroupActivity.setId(updateGroupOrder.getActivityId());
        updateGroupActivity.setName("王者之峰测试");
        inyGroupActivityDao.updateById(updateGroupActivity);
        addAssistanceStock(orderDo);
        int i=1/0;//调用方法异常
    }

被调用B方法

  @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAssistanceStock(InyGroupOrderDo orderDo) {
        Long goodsId = 8975L;
        Long skuId = 35285L;
        LsdGoodsDo goods=new LsdGoodsDo();
        goods.setId(goodsId);
        goods.setName("王者之峰测试goodName");
        lsdGoodsDao.updateById(goods);
        LsdGoodsSkuPriceDo skuPrice=new LsdGoodsSkuPriceDo();
        skuPrice.setId(skuId);
        skuPrice.setPriceAmount(BigDecimal.ZERO);
        lsdGoodsSkuPriceDao.updateById(skuPrice);
         int i=1/0;//被调用方法异常
    }

读者可以自己试试,哪一个方法有异常都会导致两个方法执行语句都不生效。

然后调用别的没有事务的方法可以把B方法的事务注解去掉,制造一个异常,看看A B执行的语句会不会生效。

弄到后面发现错了,事务注解默认同一个类只有第一级方法能被代理到,第二级也就是被调用的不会,也就是说被调用B方法加了注解和没加一样,得重新测下,修改为如下:

调用A方法

 @Transactional(rollbackFor = Exception.class)
    @Override
    public void closeOrderAndReturnStock(InyGroupOrderDo orderDo) {
        InyGroupOrderDo updateGroupOrder = new InyGroupOrderDo();
        updateGroupOrder.setId(569L);
        updateGroupOrder.setStatus(4);
        updateGroupOrder.setActivityId(12L);
        inyGroupOrderDao.updateById(updateGroupOrder);
        InyGroupActivityDo updateGroupActivity=new InyGroupActivityDo();
        updateGroupActivity.setId(updateGroupOrder.getActivityId());
        updateGroupActivity.setName("王者之峰测试");
        inyGroupActivityDao.updateById(updateGroupActivity);
         lsdGoodsSkuPriceService.addAssistanceStock();
        int i=1/0;//调用方法异常
    }

B方法不变,但是放在另一个servise里面了,这样成为了第一级方法。

但是最终测试结论不变。

propagation = Propagation.NOT_SUPPORTED

声明该方法不需要事务,如果调用的方法有事务会先挂起让事务执行,如果被事务的方法调用那么有事务的方法会被挂起。

A方法注解换成

@Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)

测试会发现该A方法sql执行马上生效不会等方法结束。

propagation = Propagation.REQUIRES_NEW

该方法无论怎样会自己新建一个事务,如果被其他有事务的方法调用,那该事务会先挂起。那么调用其他有事务的方法会被该事务异常影响嘛,自己的事务异常会影响别人嘛,那如果被其他有事务的方法调用呢外面方法异常会影响它嘛,自己异常会影响外部嘛。下面将一一测试。

  1. 首先证明是否开启了一个新事务。

事务的默认隔离级别保证了未提交的数据另外一个事务查询不到最新的,那么证明是否开启了新事务在一个事务中修改,在另外一个开启新事务的方法中会读到修改前的数据,这导致脏读,但是脏读是没有用的嘛?不一定,在一个方法里面修改再调用的方法里面想使用修改前的数据可以在被调用的方法开启新的事务这样就ok了。

  1. propagation = Propagation.REQUIRES_NEW作为内部方法出现异常会影响外部方法事务嘛?

修改B方法的propagation = Propagation.REQUIRES_NEW B方法会出现异常

测试结果是会的

那外部方法异常呢?

在A方法最下面加个异常代码

测试结果是不会的,因为内部方法开启了新的异常所以不会的。

所以如果被调用的方法是独立的事务,可以设置propagation = Propagation.REQUIRES_NEW这样外部方法后面的代码异常就不会影响内部事务了。

其实现象很正常内部方法异常会往外面抛

  1. propagation = Propagation.REQUIRES_NEW作为外部方法和内部方法异常互相的影响呢?

A方法改为 propagation = Propagation.REQUIRES_NEW B方法使用默认的,那么A异常会影响B,B异常也会影响A,因为B加入了A的事务。

此出就不验证
4. propagation = Propagation.REQUIRES_NEW作为内部方法外部异常会影响内部嘛?

在A方法制造一个异常,测试发现不会,因为B已经开启了个新的事务。

propagation = Propagation.MANDATORY

强制的,表示被注解的方法必须被已有事务的方法调用,如若不然则抛异常。

这个传播行为啥时用到呢?应该是在于A方法本来就有事务,而B是多个业务处理中的通用子业务,需要和很多A在一个事务中。

propagation = Propagation.SUPPORTS

不需要在事务环境中执行,可以加入现有事务,和没有加事务注解方法一样。

propagation = Propagation.NEVER

表示此方法不能在事务环境中,如果有就抛异常。

propagation = Propagation.NESTED

你可能感兴趣的:(Spring声明式事务@Transactional传播行为)