@Transactional注解标注方法A,调用本类方法B,如何使B方法不在A事务下执行

原由:有次开发业务代码,事务方法A中存在不强依赖事务的逻辑,将改逻辑抽取方法B,然后再用this调用B方法。按照惯性思维,B方法不走事务了,以为大功告成;实则不然B方法执行仍然和A方法处于同一事物中,那么如何才能使B方法不处于A方法的事务下执行呢?

以下以第一个方法为A方法,第二个方法为B方法称呼

## 尝试1

根据spring事务传播机制,想当然在B方法加以下注解

@Transactional(propagation = Propagation.NOT_SUPPORTED)

业务代码如下

期待的结果为dept表插入数据失败,goods表插入数据成功,实际上如下图,都没有插入数据,A方法事务对两个方法都生效

## 尝试2

A调用B方法时,用另一个线程去调用

此时发现两个表中都插入成功,看过源码的兄弟大概知道一点是spring事务是基于aop,并且事务是和线程绑定的,原码见下图,所以开启新的线程会导致事务失效,所以两个表数据都新增成功

表中数据如下

## 尝试3

利用spring异步处理,启动类加上@EnableAsync注解开启异步处理,在B方法加上@Async注解然后this调用,想当然以为和new thread一样两个表都新增成功,然而并非我们期待的那样,都新增失败事务生效,业务代码如下

至于为什么@Async注解,没起作用感兴趣的可以深入研究下

## 尝试4

在3的基础上利用代理对象去调用B方法,在启动类上加上注解@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)暴露代理对象,执行之后查看表中数据发现,两个表数据都新增成功,说明@Async注解开启了异步线程处理,所以上一步为啥没有开启异步线程应该有点思路了吧哈哈,业务代码如下:

## 尝试5

如果我不想开启新的线程也想达到B方法不处于A方法事务下,当然也有方法还是利用spring事务的传播机制进行处理,业务代码如下

此时dept表新增失败,goods表新增成功,说明B方法以非事务方式执行

## 总结

当我们本类内部务方法A调用另一个方法B时,如果想使A事务生效但是是B方法事务不生效可以有三种方式

1.手动新建线程调用B方法

2.暴露代理对象,开启spring异步处理,在B方法加上@Async注解,用代理对象调用B方法

3.利用事务的传播机制B方法加上@Transactional注解传播机制设置为NOT_SUPPORTED

可以根据个人的需要采取合适的方式去使用,希望能对你有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值