使用场景
项目有多个数据源, 根据配置文件配置的连接数来自动生成多数据源配置 并且使用 aop切换数据源,具体实现方式 网上有很多 使用的是 AbstractRoutingDataSource 重写 determineCurrentLookupKey 方法
默认数据源为ninja 第二个数据源为 test
今天要说的问题就是@Transactional 和切换数据源 @DS 同时使用时 切换数据源无效的问题
当我在一个service方法上切换了数据源时同时 加入了事务 ,此时方法中需要操作两次数据库 需要保证事务 下图:
然后在加了 @Transactional 注解后出现问题: 数据源一直都是使用的默认数据源 而非我指定的 test数据源, 然后各种查资料发现 在同一个事务中数据源是无法切换的 最终发现在我debug源码时,
1在切换数据源之前 @Transactional 先执行 切面,此时会去获取数据源,而此时数据源还没有切换 就会获取默认的数据源 源码:
2在执行完@Transactional 锁定数据源之后, @ds切面后执行, 此时切换数据源的时候只是改变了缓存数据源配置的key字符串,在执行db操作的时候没有重新根据当前字符串的key去获取最新的数据源,所以表现出 数据源未切换的现象,查询报错表名不存在
解决方法:
思考: 如果在事务获取数据源之前,切换数据源问题不就解决了吗, 查了资料发现 在自定义的切面中 加入
@Order(-1) 来执行方法上的注解的执行顺序,可以优先于@Transactional 执行
然后再次进行测试, 数据源成功切换,事务仍然有效,问题解决
注意:此事务内只能保证同一个数据源, 非分布式事务