动态数据源是这样实现的: -------------------------- 动态数据源类集成了Spring提供的AbstractRoutingDataSource类,AbstractRoutingDataSource 中获取数据源的方法就是 determineTargetDataSource,而此方法又通过 determineCurrentLookupKey 方法获取查询数据源的key。
所以如果我们需要动态切换数据源,就可以通过以下两种方式定制:
1. 覆写 determineCurrentLookupKey 方法
通过覆写 determineCurrentLookupKey 方法,从一个自定义的 DynamicDataSourceContextHolder.getDataSourceKey() 获取数据源key值,这样在我们想动态切换数据源的时候,只要通过 DynamicDataSourceContextHolder.setDataSourceKey(key) 的方式就可以动态改变数据源了。这种方式要求在获取数据源之前,要先初始化各个数据源到 DynamicDataSource 中,我们案例就是采用这种方式实现的,所以在 MybatisConfig 中把master和slave数据源都事先初始化到DynamicDataSource 中。 --------------------------
通过线程Local设置数据源Key即可。
现象: 有几个数据源,添加数据时,挨个切换,然后insert数据。 发现有一个数据源,总是插入不进去,莫名其妙。 debug跟了一下,发现也没报错,见鬼了。
后来,单步debug进去,发现conn貌似不正确,莫名其妙。
后来,发现貌似走了事务,sqlSession是从线程Local获取的,类似于缓存
查看spring配置文件,确实给insert开头的配置了事务。
关键是: DynamicDataSourceContextHolder.setDataSourceKey(key) 这东西写在了insertXX()方法里边, 既然开了事务,肯定是调用方法之前就开始了事务,肯定就获取了连接, 方法里面再切数据源,对自己肯定没毛用了,相当于给后一个loop切了数据源。
也就是:第二次循环的数据源,实际是第一次方法里面切换的。 第三次循环的数据源,实际是第二次方法里面切换的。 最后一次循环的数据源,是倒数第二个切换的。
结果就是:最后一个数据源,实际没有执行insert。
解决办法: 在调用xxService.insertXXX();之前切换数据源,问题解决。
|