首先看一下這個功能的架構設計java
Deault DataSource
,他是從配置文件中獲取的,在應用剛開始啓動時就注入,而在某些狀況下,咱們須要在一次操做中短時或長時間的對其它的數據庫進行操做,這就是所謂的數據源切換。DataSourceContextHolder
類,來保留當前線程的數據源。Session
時,會注入 DynamicDataSource
,而 DynamicDataSource
經過讀取當前線程變量能夠獲取本身設置的數據源,若是沒有設置會注入默認的數據源,這個數據源來自於配置文件,調用流程以下圖public class DataSourceContextHolder { // 當前線程使用的數據源,爲null表示默認數據源 private static final ThreadLocal<DataSource> contextHolder = new InheritableThreadLocal<DataSource>(); // 當前線程使用過的數據源,方便事務 private static final List<DataSource> dataSources = new ArrayList<>(); // 全局外部數據源緩存 private static final HashMap<String, DataSource> map = new HashMap<>(); // 設置當前線程的數據源 public static void setDataSource(DruidDataSource datasource) { if (!map.containsKey(datasource.getUrl())) { contextHolder.set(datasource); map.put(datasource.getUrl(), datasource); } else { contextHolder.set(map.get(datasource.getUrl())); } dataSources.add(contextHolder.get()); } // 獲取數據源 public static DataSource getDataSource() { return contextHolder.get(); } // 獲取數據源 public static List<DataSource> getThreadDataSources() { return dataSources; } public static void clearCache() { map.clear(); } public static void clearDataSource() { contextHolder.remove(); } }
@Configuration public class DataSourceConfig { @Bean(name = "defaultDataSource") @ConfigurationProperties(prefix = "jdbc") public DataSource defaultDataSource() { return new DruidDataSource(); } @Bean(name = "dynamicDataSource") public DynamicDataSource dynamicDataSource() { return new DynamicDataSource(); } }
/** * 動態數據源管理類 */ public class DynamicDataSource extends AbstractDataSource { // 注入默認數據源 @Resource(name = "defaultDataSource") private DataSource defaultDs; protected DataSource determineTargetDataSource() { // 獲取當前線程的數據源 DataSource dataSource = DataSourceContextHolder.getDataSource(); // 若是沒有設置動態數據源,則返回默認數據源 if (dataSource == null) { return defaultDs; } return dataSource; } @Override public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } @Override public Connection getConnection(String username, String password) throws SQLException { return determineTargetDataSource().getConnection(username, password); } }
@Configuration public class MyBatisConfig { @Resource(name = "dynamicDataSource") private DynamicDataSource dynamicDataSource; @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setObjectWrapperFactory(new MapWrapperFactory()); // 設置數據源爲DynamicDataSource sqlSessionFactoryBean.setDataSource(dynamicDataSource); sqlSessionFactoryBean.setTypeAliasesPackage("me.ezerror.pojo"); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate financialMasterSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }
// 新建數據源 DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setPassword(pwd); dataSource.setUsername(username); // 設置數據源 DataSourceContextHolder.setDataSource(dataSource); // 數據庫操做 List<Moment> moments = recordService.findMoment(); // 清除數據源,還原到默認數據源 DataSourceContextHolder.clearDataSource();