多数据源切换(三)
业务背景
在上一节中的思考题中:假如我们将事务@Transactional 注解加在Controller的方法上,又会出现无法切换数据源,只会使用主数据源。
本文主要探究并解决@DS加上@Transactional 注解失效的问题
探究
由于在Controller层加上了@Transactional注解,导致masterUserService.insert(masterUser)和externalUserService.unionTransactional(externalUser)在同一个事务中(基于master_db的事务),因此在externalUserService.unionTransactional(externalUser)的切面中AbstractRoutingDataSource判断datasource时:datasource不为null,导致使用默认数据源。
效果类似于下图
解决思路
既然externalUserService.unionTransactional(externalUser)使用了基于masterUserService.insert(masterUser)产生的事务,那么只需要externalUserService.unionTransactional(externalUser)新开一个属于externalUserService.unionTransactional(externalUser)的事务即可。
解决方案
在externalUserService实现类上指定事务的传播属性为新开一个事务即可
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
如下图
调取localhost:8080//insert/union 接口
查看数据库结果
思考题?
当事务B提交后,出现了异常:这个时候事务A会回滚,但事务B不会回滚。假如需要同时回滚该怎么做?
解决方案:需要分布式事务,分布式事务的参考的原理及组件参考:
seata官网
其中Spring官方推荐使用Atomkios来实现XA协议