本文主要講解基於MybatisPlus開源框架組件Dynamic動態數據源切換
1、pom配置文件(這里僅展示動態數據源切換的核心依賴,具體jar包版本根據你的項目實際情況確定)
<!-- baomidou的動態數據源切換插件,版本最好與mybatisplus保持一致 -->
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.3.2</version> </dependency>
<!--Mysql驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--Druid連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--Mybatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
2、yaml文件配置
spring:
autoconfigure:
#自動化配置 例外處理
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
datasource:
type: com.alibaba.druid.pool.DruidDataSource
dynamic:
primary: mysql #默認數據源
datasource:
mysql:
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8
username: root
password: 123123
driver-class-name: com.mysql.cj.jdbc.Driver
oracle:
url: jdbc:oracle:thin:@127.0.0.1:1521:xe
username: system
password: 123123
driver-class-name: oracle.jdbc.OracleDriver
druid:
max-active: 50
max-wait: 10000
min-idle: 3
initial-size: 5
mybatis-plus:
mapper-locations: classpath:/mapper/*Mapper.xml
#實體掃描,多個package用逗號或者分號分隔
typeAliasesPackage: cn.example.entity
以上兩步完成,啟動項目,項目如果啟動成功,就代表數據源配置完成了
3、動態數據源切換
3.1、硬編碼指定數據源
這種方式是通過插件提供的DS注解來實現的:com.baomidou.dynamic.datasource.annotation.DS,用例如下:
import cn.example.entity.Test;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@DS("oracle")//可以使用在類上
@Repository
public interface TestMapper extends BaseMapper<Test> {
List<String> queryDataGroups();
List<String> queryDataTableNames();
List<String> queryDataTypes();
@DS("oracle")//也可以使用在方法上
List<Map> sqlQuery(String queryContext);
}
3.2、動態指定數據源
第二種方式是請求時指定數據源,其實就是第一宗方式的變種,對於通過注解的方式,其內部實現原理也是在請求時通過AOP攔截到DS注解,然后設置當前請求的數據源的key,具體源碼如下:

而在執行時,是這么獲取數據源的:

這里看一下DynamicDataSourceContextHolder類內部結構:

通過源碼我們可以發現,只要在執行SQL前調用DynamicDataSourceContextHolder設置當前需要使用的數據源,並且在使用后刪除指定key就可以了,下面是我的代碼demo
public Object sqlQuery(String queryContext,String dataSource) {
if (StringUtils.isBlank(queryContext))
return null;
DynamicDataSourceContextHolder.push(dataSource);
try {
queryContext = queryContext.trim();
log.info("執行SQL:{}",queryContext);
return testMapper.sqlQuery(queryContext);
} catch (Exception e) {
log.error("SQL執行錯誤:" + queryContext, e);
} finally {
DynamicDataSourceContextHolder.poll();
}
return null;
}
這種方式還需要提供數據源列表供接口調用方去選擇,因此需要提供一個數據源列表查詢功能,實際上看一下DynamicRoutingDataSource的內部實現就知道了,它其實維護了一個map來存儲數據源,我們拿到這個map的所有key就可以了

下面的我的代碼demo
@Autowired
DynamicRoutingDataSource dynamicRoutingDataSource;
@Override
public Object dataSources() {
Map<String, DataSource> currentDataSources = dynamicRoutingDataSource.getCurrentDataSources();
return currentDataSources.keySet();
}
