Spring 如何在一个事务中开启另一个事务?
这样的情景可能不常见,但是还是会有的,一旦遇到,如果业务比较复杂,就会很麻烦,但是还是有解决的方案的,比如将一个service方法拆成两个方法,也就是将两个操作的事务分开。
但是这只适用与业务比较简单的,如果出现多次数据库的写操作,而我们调用的系统只需要其中一个写操作的最新数据,如果我们将它分开,那么如果调用目标系统出现异常的时候,那么之前的写操作就不能回滚了。
举个简单的例子:
@Service
public class ServiceA {
@Transactional
public void doSomething(){
向数据库中添加数据;
调用其他系统;
}
}
这里就用伪代码来做示例了,当我们执行了“向数据库中添加数据”,我们去数据库中查询,发现并没有我们添加的数据,但是当我们的service这个方法执行完成之后,数据库中就有这条数据了,这是由于数据库的隔离性造成的。
Spring中的事务注解 @transactional 提供了一个参数:
Propagation propagation() default Propagation.REQUIRED;
这个参数是定义 Spring事务的传递性的,默认值为:required,也就是如果有事务,就加入事务,如果没有,就创建事务。
这个参数的值有很多,例如:REQUIRES_NEW,这个值就代表创建一个新的事务,与原来的事务分开。这个好像能解决我们的问题。关注Java技术栈公众号在后台回复:spring,可获取一份栈长整理的最新 Spring 系列技术干货。
我们将刚刚那个方法修改一下:
@Service
public class ServiceA {
@Transactional
public void doSomething(){
insert();
调用其他系统;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insert(){
向数据库中添加数据;
}
}
执行之后,发现结果还是没有改变,必须要整体执行完成,数据库中数据才会出现,说明还是在一个事务中。Spring的核心思想,推荐你看看。
我们再将代码修改一下:
@Service
public class ServiceA {
@Autowired
private ServiceB serviceB;
@Transactional
public void doSomething(){
serviceB.insert();
调用其他系统;
}
}
@Service
public class ServiceB {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insert(){
向数据库中添加数据;
}
}
我们将要事务分离出来的方法写在另一个service中,再次测试,发现执行完插入语句之后,数据库中就已经能查到数据了,说明事务分离了,完成了我们的需求。
当然** Spring**其实也考虑这个,在 Spring的配置中,我们只需要添加标签:
aop:aspectj-autoproxy expose-proxy="true"/
或者:
aop:config expose-proxy="true"
并且在代码的调用中要求使用代理对象去调用即可:
((ServiceA ) AopContext.currentProxy()).insert();
关注公众号Java技术栈回复"面试"获取我整理的2020最全面试题及答案。
推荐去我的博客阅读更多:
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
觉得不错,别忘了点赞+转发哦!
相关文章
- Spring事务失效常见的八种场景
- Spring Data默认值的错误
- ssm整合之Spring整合MyBatis框架配置事务
- spring与mybatis三种整合方法
- Spring-4.0 + Quartz-2.2.1 集群实例(Tomcat+Memcached+Quartz集群session共享)还是没有解决Serializable序列化
- spring的annotation-driven配置事务管理器详解
- 一文带你认识Spring事务
- Spring框架10:spring编程式事务控制
- Spring中解决Hibernate的lazy加载问题
- JBPM4.4_jBPM4.4应用(与Spring集成&自行控制事务等)
- SPRING声明式事务,不写rollback-for的问题
- spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象
- 万字长文 | Spring Cloud Alibaba组件之Nacos实战及Nacos客户端服务注册源码解析
- spring事务失效的几种场景以及原因
- 解析spring事务管理@Transactional为什么要添加rollbackFor=Exception.class(事务失效)
- spring成神之路第四十八篇:@Transaction 事务源码解析
- spring成神之路第四十七篇:spring 编程式事务源码解析
- spring成神之路第四十三篇:spring 中编程式事务怎么用的?
- 已解决org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.Bi
- spring的事务是什么?与数据库的事务是否一样
- Spring Boot2 系列教程(三)理解 Spring Boot 项目中的 parent
- 在Spring Boot中使用数据库事务
- 分布式事务、多数据源、分库分表中间件之spring boot基于Atomikos+XADataSource分布式事务配置(100%纯动态)