介绍
MP集成多数据源的官方文档:多数据源 | MyBatis-Plus
特性
- 支持无数据源启动,支持懒加载数据源(需要的时候再创建连接)
- 提供 基于seata的分布式事务方案
约定
- 本框架只做切换数据源这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD
- 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换
- @DS注解支持ServiceImpl,暂不支持Service接口上的@DS注解
导入依赖
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.11</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--Mybatis Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--配置多个数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
配置文件
配置一主一从
spring:
datasource:
dynamic:
primary: master #设置默认的数据源或者数据源组, 默认值即为master
strict: false #严格匹配数据源,默认false,true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
# 主数据源
master:
url: jdbc:mysql://localhost:3306/table1?serverTimezone=Asia/Shanghai&useSSL=false&nullCatalogMeansCurrent=true
username: root
password: "password"
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
# 从数据源
slave_1:
url: jdbc:mysql://localhost:3306/table2?serverTimezone=Asia/Shanghai&useSSL=false&nullCatalogMeansCurrent=true
username: root
password: "password"
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
其他配置模式
# 多主多从 纯粹多库(记得设置primary) 混合配置
spring: spring: spring:
datasource: datasource: datasource:
dynamic: dynamic: dynamic:
datasource: datasource: datasource:
master_1: mysql: master:
master_2: oracle: slave_1:
slave_1: sqlserver: slave_2:
slave_2: postgresql: oracle_1:
slave_3: h2: oracle_2:
@DS注解
在ServiceImpl类/ServiceImpl类的方法上加@DS注解
-
注解加到ServiceImpl类上 --> 类里的方法都使用此数据源
-
注解加到ServiceImpl的方法上 --> 使用方法上的注解的数据源(方法上的注解 优先于 类上注解)
@Service
@DS("slave_1")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Resource
private UserMapper userMapper;
@Override
@DS("master")
public List<User> getUser() {
return userMapper.selectList(null);
}
}
不加@DS注解,使用默认数据源,默认值master数据源
注意事项
启动主类需要排除Druid相关依赖
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
否则会出现如下错误
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
事务中使用@DS注解
@Service("serviceA")
public class ServiceImpl implements Service{
@Override
@DS("database1")
public void functionA() {
functionB(); //调用B方法且切换为B方法的所需要的数据源
}
@Override
@DS("database2")
public void function B() {}
}
A方法调用B方法时,B方法的@DS注解不生效,会使用A方法配置的数据源,B方法的@DS("database2")将完全被A方法的@DS("database1")所覆盖。
解决: 在事务内是无法使用@DS进行切换数据源,在ServiceImpl的方法上使用下面注解,在执行此方法时,挂起外部事务,创建一个新的内部事务。
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)