项目有多个数据源, 根据配置文件配置的连接数来自动生成多数据源配置 并且使用 aop切换数据源,、使用的是 AbstractRoutingDataSource 重写 determineCurrentLookupKey 方法。
在切换数据源之前 @Transactional 先执行 ,此时会去获取数据源,而此时数据源还没有切换 就会获取默认的数据源 。 这种情况会导致数据源切换失败
源码:
如果不用事务,切换数据源是可以的。
2, 其它方式
@Configuration
@MapperScan(basePackages = "com.modules.**.dao",sqlSessionTemplateRef = "masterSqlSessionTemplate")
public class MasterDataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.master")//设置配置
public DataSource masterDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public SqlSessionFactory masterSqlSessionFactory() throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(masterDataSource());
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/master/**/*.xml"));
return bean.getObject();
}
@Bean
@Primary
public DataSourceTransactionManager masterTransactionManager() {
return new DataSourceTransactionManager(masterDataSource());
}
@Bean(name = "masterSqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate()
throws Exception {
return new SqlSessionTemplate(masterSqlSessionFactory());
}
}
@Configuration
@MapperScan(basePackages = "com.dao",sqlSessionTemplateRef = "twoSqlSessionTemplate")
public class TwoDataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.sqlserver")//设置配置
public DataSource twoDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory twoSqlSessionFactory() throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(twoDataSource());
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/two/**/*.xml"));
return bean.getObject();
}
@Bean
public DataSourceTransactionManager twoTransactionManager() {
return new DataSourceTransactionManager(twoDataSource());
}
@Bean(name = "twoSqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate()
throws Exception {
return new SqlSessionTemplate(twoSqlSessionFactory());
}
}
**非primary的事务管理器 需要在@Transactional中加上事务管理器beanName, 不能事务不会起作用, 默认使用的是primary的事务管理器**
@Autowired
private MasterMapper masterMapper;
@Autowired
private TwoMapper twoMapper;
@RequestMapping("/test")
@Transactional(rollbackFor = Exception.class)
public void report(){
twoMapper.saveConfig(info);
int i = 1 /0;
}
// 非primary的事务管理器 需要在@Transactional中加上事务管理器beanName
@RequestMapping("/test1")
@Transactional(rollbackFor = Exception.class,value = "twoTransactionManager")
public void test1(){
masterMapper.save(info);
int i = 1 / 0;
}
注意:此事务内只能保证同一个数据源, 非分布式事务
参考: https://blog.csdn.net/study_zmm/article/details/106790031
http://www.linhao007.com/2017/11/23/01/