我们在使用spring中动态数据源的时候,往往在业务代码中需要指定数据源,在进行业务操作的时候就会去指定的数据源操作数据:代码如下
数据源,两个数据源,ds1,ds2:
@Bean
public DataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
ComboPooledDataSource ds1 = getDs1();
targetDataSources.put("ds1", ds1);
targetDataSources.put("ds2", getDs2());
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(ds1);
return dynamicDataSource;
}
业务代码切换数据源代码如下:
@TargetSource("ds1")
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void transation(ConsultConfigArea area, ZgGoods zgGoods) {
areaService.addArea(area);
goodsService.addGoods(zgGoods);
}
@TargetSource("ds2")
@Transactional(propagation = Propagation.REQUIRED)
@Override
public int addArea(ConsultConfigArea area) {
int i = commonMapper.addArea(area);
return i;
}
@TargetSource("ds2")
@Transactional
@Override
public void addGoods(ZgGoods zgGoods) {
int i = commonMapper.addGood(zgGoods);
}
我们的意图是,areaService.addArea(area);需要切换到ds2数据源。
测试结论:areaService.addArea(area);还是使用的ds1数据源连接对象,也就是前面那个事务的数据源连接对象。也就是说@TargetSource("ds2")注解失效了。
为什么会这样呢?
因为spring的事务传播属性导致的,前面那个 transation 方法已经有事务了,而transation方法下面的addArea方法事务传播属性是 propagation = Propagation.REQUIRED 这个传播属性就决定了addArea方法还是使用的 transation 方法的数据源连接对象,所以当执行到addArea的时候根本就不存在创建新的连接对象的可能
由于addArea采用的是 Propagation.REQUIRED传播属性,就不存在事务的挂起和doBegin操作,还是沿用的前面方法的数据库连接对象,所以这时候是没有从数据库连接池里面拿连接的。ok,看看doBegin方法:
只有走到doBegin方法时,spring才会从连接池对象中拿连接对象,而现在是没走到doBegin方法中来,所以addArea方法还是沿用的之前的连接对象,所以这里的@TargetSource("ds2")注解其实是没起作用的。
OK,希望得到帮助的同学,点个赞,谢谢