本文主要讲解基于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();
}