1、枚舉多數據源-定義一一對應變量
/**
*
* 列出所有的數據源key(常用數據庫名稱來命名)
* 注意:
* 1)這里數據源與數據庫是一對一的
* 2)DatabaseType中的變量名稱就是數據庫的名稱
*/
public enum DatabaseType {
test1,test2
}
2、將數據源變量保存在線程變量中
/**
*
* 作用:1、保存一個線程安全的DatabaseType容器
*/
public class DatabaseContextHolder {
//將數據源枚舉變量保存在線程變量中
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>();
public static void setDatabaseType(DatabaseType type) {
contextHolder.set(type);
}
public static DatabaseType getDatabaseType() {
return contextHolder.get();
}
}
3、動態數據源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 動態數據源(需要繼承AbstractRoutingDataSource)
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}
4、數據源配置
數據源1:
test1.driverClassName=org.postgresql.Driver
test1.url=jdbc:postgresql://localhost:5432/test1
test.username=test1
test1.password=123456
test1.remove-abandoned=true
test1.remove-abandoned-timeout=120
test1.test-on-borrow=true
數據源2:
test2.driverClassName=org.postgresql.Driver
test2.url=jdbc:postgresql://localhost:5432/test2
test2.username=test2
test2.password=123456
test2.remove-abandoned=true
test2.remove-abandoned-timeout=120
test2.test-on-borrow=true
5、數據源初始化
/**
* springboot集成mybatis的基本入口
* 1)創建數據源(如果采用的是默認的tomcat-jdbc數據源,則不需要)
* 2)創建SqlSessionFactory
* 3)配置事務管理器,除非需要使用事務,否則不用配置
*
*/
@Configuration // 該注解類似於spring配置文件
@MapperScan(basePackages = "cn.test.mapper")
public class MyBatisConfig {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private Environment env;
@Bean
public DataSource test1DataSource() throws Exception {
Properties props = new Properties();
props.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, env.getProperty("test1.driverClassName"));
props.put(DruidDataSourceFactory.PROP_URL, env.getProperty("test1.url"));
props.put(DruidDataSourceFactory.PROP_USERNAME, env.getProperty("test1.username"));
// 獲取數據庫密碼
props.put(DruidDataSourceFactory.PROP_PASSWORD, env.getProperty("test1.password"));
props.put(DruidDataSourceFactory.PROP_REMOVEABANDONED, env.getProperty("test1.remove-abandoned"));
props.put(DruidDataSourceFactory.PROP_REMOVEABANDONEDTIMEOUT, env.getProperty("test1.remove-abandoned-timeout"));
props.put(DruidDataSourceFactory.PROP_TESTONBORROW, env.getProperty("test1.test-on-borrow"));
return DruidDataSourceFactory.createDataSource(props);
}
@Bean
public DataSource test2DataSource() throws Exception {
Properties props = new Properties();
props.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, env.getProperty("test2.driverClassName"));
props.put(DruidDataSourceFactory.PROP_URL, env.getProperty("test2.url"));
props.put(DruidDataSourceFactory.PROP_USERNAME, env.getProperty("test2.username"));
// 獲取數據庫密碼
props.put(DruidDataSourceFactory.PROP_PASSWORD, env.getProperty("test2.password"));
props.put(DruidDataSourceFactory.PROP_REMOVEABANDONED, env.getProperty("test2.remove-abandoned"));
props.put(DruidDataSourceFactory.PROP_REMOVEABANDONEDTIMEOUT, env.getProperty("test2.remove-abandoned-timeout"));
props.put(DruidDataSourceFactory.PROP_TESTONBORROW, env.getProperty("test2.test-on-borrow"));
return DruidDataSourceFactory.createDataSource(props);
}
/**
* @throws Exception
* @Primary 該注解表示在同一個接口有多個實現類可以注入的時候,默認選擇哪一個,而不是讓@autowire注解報錯
* @Qualifier 根據名稱進行注入,通常是在具有相同的多個類型的實例的一個注入(例如有多個DataSource類型的實例)
*/
@Bean
@Primary
public DynamicDataSource dataSource() throws Exception {
DataSource dataSource1 = test1DataSource();
DataSource dataSource2 = test2DataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DatabaseType.test1, dataSource1);
targetDataSources.put(DatabaseType.test2, dataSource2);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);// 該方法是AbstractRoutingDataSource的方法
dataSource.setDefaultTargetDataSource(dataSource1 );// 默認的datasource設置為dataSource 1
return dataSource;
}
/**
* 根據數據源創建SqlSessionFactory
*/
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource ds) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(ds);// 指定數據源(這個必須有,否則報錯)
// 加載配置mybatis-config
DefaultResourceLoader configResourceLoader = new DefaultResourceLoader();
Resource configResource = configResourceLoader.getResource("mybatis-config.xml");
bean.setConfigLocation(configResource);
// 添加mapper文件XML目錄
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:cn/test/mapper/*.xml");
bean.setMapperLocations(resources);
return bean.getObject();
}
/**
* 配置事務管理器
*/
@Bean
public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
return new DataSourceTransactionManager(dataSource);
}
}
6、
①查詢test1的數據時,可以直接調用對應的mapper;(因為test1是默認數據源)
②查詢test2的數據時,需要在調用之前指定數據源,如下代碼:
DatabaseContextHolder.setDatabaseType(DatabaseType.test2);
③同時需要查詢test1和test2的數據時,需要在調用之前指定正確的數據源。