以前业务上遇到过spring boot项目中配置多数据源问题!当时其实一直遗留着一个多数据源事务问题,没有解决!这几天闲暇,又从网上搜索了一下资料,进行了整理!
一定要注意:是两个问题!
第一:spring boot处理多数据源动态切换问题!
第二:多数据源的事务问题处理!
spring boot处理多数据源动态切换
这里主要通过 AbstractRoutingDataSource 实现动态数据源的切换
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
//AbstractRoutingDataSource获取数据源之前会先调用
//determineCurrentLookupKey方法查找当前的lookupKey
//这个lookupKey就是数据源标识
String dataSourceName = DynamicDataSourceHolder.getDataSource();
if(dataSourceName==null||dataSourceName==""){
log.info("当前数据源为: 默认数据源");
}else{
log.info("当前数据源为: "+dataSourceName);
}
return dataSourceName;
}
}
@Bean(name = "test1DataSource")
public DataSource test1DataSource() {
DruidXADataSource druidXADataSource = new DruidXADataSource();
//初始化数据源
initDruidXADataSource(druidXADataSource, test1DataSourceProperties());
//将数据源交给 atomikos 是为了后面的事务准备的
return atomikosOption("atomikos_test1DataSource", druidXADataSource);
}
@Bean(name = "test2DataSource")
public DataSource test2DataSource() {
DruidXADataSource druidXADataSource = new DruidXADataSource();
initDruidXADataSource(druidXADataSource, test2DataSourceProperties());
return atomikosOption("atomikos_test2DataSource", druidXADataSource);
}
@Bean
public DataSource dynamicDataSource() {
DataSource test1= test1DataSource();
DataSource test2= test2DataSource();
Map<Object, Object> targetDataSources = Maps.newHashMap();
targetDataSources.put("test1", test1);
targetDataSources.put("test2", test2);
DynamicDataSource dynmicDataSource = new DynamicDataSource();
dynmicDataSource.setTargetDataSources(targetDataSources);
//设置默认数据源
dynmicDataSource.setDefaultTargetDataSource(test1);
return dynmicDataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//在此处获取的数据源就是你根据 DynamicDataSource 处理后获取的数据源
//因为是demo,我没用进行写成注解类处理
//有兴趣的小伙伴可以自己去写一下!
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
sqlSessionFactoryBean.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
//使用自定义事务工厂 这里注意:如果你不重写spring的事务注解
//在一个事务里面是无法进行数据源的切换的
sqlSessionFactoryBean.setTransactionFactory(new MultiDataSourceTransactionFactory());
return sqlSessionFactoryBean.getObject();
}
多数据源的事务处理
最简单的方法就是,将数据源交给 Atomikos 进行管理
网上有很多例子写了一堆 bean,UserTransaction,atomikosTransactionManager等等,我感觉没用!跟atomikos默认的应该一样!只要把数据源交给 atomikos 即可.
两个库的表进行了插入操作!
然后删除了数据库数据,再进行一个错误操作,如下:
两个表都没有数据插入!说明事务起作用了!
在这里非常感谢:@我爱喝可乐 https://blog.csdn.net/gaoshili001/article/details/79378902 文章说明的很详细!