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