@DS 注解是 MyBatis-Plus 提供的动态数据源切换注解,以下是其详细使用方法:
添加依赖
在项目中引入 dynamic-datasource-spring-boot-starter 依赖,其版本需根据实际使用的 Spring Boot 版本和 MyBatis-Plus 版本进行选择,例如:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
配置数据源
在 application.properties 或 application.yml 文件中配置多个数据源。例如:
spring:
datasource:
dynamic:
primary: master # 设置主数据源
strict: false # 是否开启严格模式
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/master_db
username: root
password: root
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/slave_db
username: root
password: root
使用 @DS 注解
• 标注在方法上 :在需要切换数据源的方法上添加 @DS 注解,指定具体的数据源名称。例如:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@DS("master")
public List<User> listUsersFromMaster() {
return userMapper.selectList(null);
}
@DS("slave")
public List<User> listUsersFromSlave() {
return userMapper.selectList(null);
}
}
当调用 listUsersFromMaster 方法时,会使用名称为 “master” 的数据源;调用 listUsersFromSlave 方法时,则使用名称为 “slave” 的数据源。
• 标注在类上 :若在一个类上添加 @DS 注解,则该类中的所有方法默认都使用指定的数据源。但若类中的某个方法也标注了 @DS 注解,则方法上的注解会覆盖类上的注解,以方法指定的数据源为准。例如:
@DS("slave")
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> listUsers() {
return userMapper.selectList(null);
}
@DS("master")
public void updateUser(User user) {
userMapper.updateById(user);
}
}
该 UserService 类中大部分方法使用 “slave” 数据源,但 updateUser 方法使用 “master” 数据源。
使用 SpEL 表达式动态指定数据源
@DS 注解中可以使用 Spring 的 SpEL 表达式来动态决定使用哪个数据源。例如:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> listUsersByDataSource(String dataSourceName) {
DynamicDataSourceContextHolder.push(dataSourceName);
return userMapper.selectList(null);
}
}
也可以在注解中直接写 SpEL 表达式:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@DS("#{T(java.lang.ThreadLocal).get().dataSourceName}")
public List<User> listUsers() {
return userMapper.selectList(null);
}
}
需先通过 DynamicDataSourceContextHolder 设置数据源名称到 ThreadLocal 中,然后在注解中通过 SpEL 表达式获取并使用该数据源名称。
动态切换数据源的实现原理
• 核心组件 :@DS 注解的实现主要依赖于 DynamicDataSourceAnnotationInterceptor 切面和 DynamicDataSourceContextHolder 工具类。DynamicDataSourceAnnotationInterceptor 切面会拦截带有 @DS 注解的方法或类,在方法执行前,获取注解中指定的数据源名称,并将其存储到 DynamicDataSourceContextHolder 的 ThreadLocal 变量中。
• 数据源切换 :DynamicRoutingDataSource 是一个动态数据源路由类,继承自 AbstractRoutingDataSource。它会根据 DynamicDataSourceContextHolder 中存储的数据源名称,从配置的数据源集合中选择对应的数据源进行切换,从而实现动态数据源切换。