目錄
一、禁掉SpringBoot的自動配置數據源類,並寫新的配置類
在實際中,一個項目一般只會對應着一個數據源,但也有些需要多個數據源的項目。在本文中,會介紹SpringBoot + Mybatis框架下如何配置多個數據源,並能代碼中自主切換。
一、禁掉SpringBoot的自動配置數據源類,並寫新的配置類
在SpringBoot中,程序會自動讀取src/main/resources/application.properties文件中的spring.datasource.xxx的數據源配置信息,所以我們需要配置多數據源的話,要先把這個自動讀取數據源配置信息的類禁掉。禁掉該類的方法是:在SpringBoot的啓動類中,使用@SpringBootApplication註解時把該類(DataSourceAutoConfiguration.class)排除。代碼如下:
/**
* SpringBoot啓動程序
*
* @author hrc
* @date 2018年10月9日
*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) // 禁掉
@EnableAutoConfiguration
@MapperScan("com.zldc.weekly.mapper")
public class StarApp extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(StarApp.class);
}
public static void main(String[] args) {
SpringApplication.run(StarApp.class, args);
}
}
禁掉自動讀取數據源配置類之後,需要自己寫讀取不同數據源的配置信息代碼了,要配置多少個數據源,就多少個配置方法,相關代碼如下:
/**
* mysql數據源
* @return
*/
@Bean("mysql") // bean的名稱
@ConfigurationProperties(prefix = "spring.datasource.mysql") // application.properteis中對應屬性的前綴
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
/**
* oracle數據源
* @return
*/
@Bean("oracle") // bean的名稱
@ConfigurationProperties(prefix = "spring.datasource.oracle") // application.properteis中對應屬性的前綴
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
二、自動切換數據源
數據源類型常量類(也可以是枚舉類),具體代碼如下:
/**
* 數據源名稱
*
* @author hrc
* @date 2018年10月9日
*/
public class DataSourceDialect {
public static final String ORACLE="oracle";
public static final String MYSQL="mysql";
}
數據源切換類,構建一個數據源類型容器,並提供了向其中設置、獲取和清空數據源類型的方法,具體代碼如下:
/**
* 數據源類型容器
*
* @author hrc
* @date 2018年10月9日
*/
public class DataSourceSwitch {
/**
* 保存數據源類型線程安全容器
*/
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
/**
* 設置數據源類型
* @param dataSourceType 數據源類型
*/
public static void setDataSourceType (String dataSourceType) {
contextHolder.set(dataSourceType);
}
/**
* 獲取數據源類型
* @return
*/
public static String getDataSourceType(){
return (String) contextHolder.get();
}
/**
* 清空數據源類型
*/
public static void clearDataSourceType(){
contextHolder.remove();
}
}
動態切換數據源類,該類需要繼承AbstractRoutingDataSource類,並重寫determineCurrentLookupKey()方法,從數據源類型容器中獲取當前線程的數據源類型。相關代碼如下:
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitch.getDataSourceType();
}
}
三、重寫SpringBoot的數據源配置
根據新配置的多數據源和新寫的動態切換數據源類,配置新的SpringBoot數據源,具體代碼如下:
/**
* 動態數據源配置
*
* @return
*/
@Primary
@Bean("dataSource")
public DynamicDataSource dataSource(@Qualifier("mysql") DataSource mysql,
@Qualifier("oracle") DataSource oracle) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceDialect.MYSQL, mysql);
targetDataSources.put(DataSourceDialect.ORACLE, oracle);
dynamicDataSource.setTargetDataSources(targetDataSources);
// 設置默認的數據源
dynamicDataSource.setDefaultTargetDataSource(mysql);
return dynamicDataSource;
}
根據動態數據源配置,創建sqlSessionFactory,具體代碼如下:
@Primary
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("mysql") DataSource mysql, @Qualifier("oracle") DataSource oracle) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(this.dataSource(mysql, oracle));
sessionFactory.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapper-locations")));
return sessionFactory.getObject();
}
根據動態數據源配置,創建transactionManager,具體代碼如下:
@Bean("transactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DynamicDataSource dataSource) throws Exception {
return new DataSourceTransactionManager(dataSource);
}
四、數據源配置類的整合代碼
/**
* 數據源配置
* @author hrc
* @date 2018年10月9日
*/
@Configuration
public class DataSourceConfig {
@Autowired
private Environment env;
/**
* mysql數據源
* @return
*/
@Bean("mysql") // bean的名稱
@ConfigurationProperties(prefix = "spring.datasource.mysql") // application.properteis中對應屬性的前綴
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
/**
* oracle數據源
* @return
*/
@Bean("oracle") // bean的名稱
@ConfigurationProperties(prefix = "spring.datasource.oracle") // application.properteis中對應屬性的前綴
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 動態數據源配置
* @return
*/
@Primary
@Bean("dataSource")
public DynamicDataSource dataSource(@Qualifier("mysql") DataSource mysql,
@Qualifier("oracle") DataSource oracle) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceDialect.MYSQL, mysql);
targetDataSources.put(DataSourceDialect.ORACLE, oracle);
dynamicDataSource.setTargetDataSources(targetDataSources);
// 設置默認的數據源
dynamicDataSource.setDefaultTargetDataSource(mysql);
return dynamicDataSource;
}
@Primary
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("mysql") DataSource mysql, @Qualifier("oracle") DataSource oracle) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(this.dataSource(mysql, oracle));
sessionFactory.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapper-locations")));
return sessionFactory.getObject();
}
@Bean("transactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DynamicDataSource dataSource) throws Exception {
return new DataSourceTransactionManager(dataSource);
}
}