点击上方 "程序员小乐"关注, 星标或置顶一起成长
每天凌晨00点00分, 第一时间与你相约
每日英文
There is always that one person who can send you a text and cause you to smile instantly.
总有那么有一个人,他的一条短信就可以让你立刻微笑。
每日掏心话
当时觉得很大压力,后来回望,不过是多么的微小。
来自:Mazin | 责编:乐乐
链接:my.oschina.net/u/3441184/blog/893628
程序员小乐(ID:study_tech)第 753 次推文 图片来自 Pexels
往日回顾:“公司年终奖发了个锤子!”你的年终奖发了吗?别人家公司送房送车、现金、iPhone...
正文
Spring项目,需要在一个事务中开启另一个事务。
上面提到的情景可能不常见,但是还是会有的,一旦遇到,如果业务比较复杂,就会很麻烦,但是还是有解决的方案的,比如将一个service方法拆成两个方法,也就是将两个操作的事务分开。
但是这只适用于业务比较简单的,如果出现多次数据库的写操作,而我们调用的系统只需要其中一个写操作的最新数据,如果我们将它分开,那么如果调用目标系统出现异常的时候,那么之前的写操作就不能回滚了。
举个简单的例子:
@Servicepublic class ServiceA { @Transactional public void doSomething(){ 向数据库中添加数据; 调用其他系统; }}
这里就用伪代码来做示例了,当我们执行了“向数据库中添加数据”,我们去数据库中查询,发现并没有我们添加的数据,但是当我们的service这个方法执行完成之后,数据库中就有这条数据了,这是由于数据库的隔离性造成的。
spring中的事务注解@transactional提供了一个参数:
Propagation propagation() default Propagation.REQUIRED;
这个参数是定义spring事务的传递性的,默认值为required,也就是如果有事务,就加入事务,如果没有,就创建事务。这个参数的值有很多,例如REQUIRES_NEW,这个值就代表创建一个新的事务,与原来的事务分开。这个好像能解决我们的问题。
我们将刚刚那个方法修改一下:
@Servicepublic class ServiceA { @Transactional public void doSomething(){ insert(); 调用其他系统; } @Transactional(propagation = Propagation.REQUIRES_NEW) public void insert(){ 向数据库中添加数据; }}
执行之后,发现结果还是没有改变,必须要整体执行完成,数据库中数据才会出现,说明还是在一个事务中。
我们再将代码修改一下:
@Servicepublic class ServiceA { @Autowired private ServiceB serviceB; @Transactional public void doSomething(){ serviceB.insert(); 调用其他系统; }}
@Servicepublic class ServiceB { @Transactional(propagation = Propagation.REQUIRES_NEW) public void insert(){ 向数据库中添加数据; }}
我们将要事务分离出来的方法写在另一个service中,再次测试,发现执行完插入语句之后,数据库中就已经能查到数据了,说明事务分离了,完成了我们的需求。
当然spring其实也考虑这个,在spring的配置中,我们只需要添加标签 <aop:aspectj-autoproxy expose-proxy="true"/> 或者 <aop:config expose-proxy="true"> ,并且在代码的调用中要求使用代理对象去调用即可:
<aop:aspectj-autoproxy expose-proxy="true"/>
<aop:config expose-proxy="true">
((ServiceA ) AopContext.currentProxy()).insert();
欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人。
欢迎各位读者加入程序员小乐技术群,在公众号后台回复“加群”或者“学习”即可。
猜你还想看
阿里、腾讯、百度、华为、京东最新面试题汇集
Java中关于try、catch、finally中的细节分析,看了都说好!
Google 开源的依赖注入库,比 Spring 更小更快!
为什么要看源码?如何看源码?高手进阶必看!
文章有问题?点此查看未经处理的缓存