MyBatis Plus 的 多数据源支持是通过 DataSource 来实现的,它允许在同一个应用中同时连接多个数据库,适用于多种场景:纯粹多库、读写分离、一主多从、混合模式等
模拟一个纯粹多库的一个场景,其他场景类似
1、创建数据和表
在数据库 springbootdemo 中创建 t_employee 表,在数据库 springbootdemo1 中创建同名数据表
sql
CREATE TABLE t_employee (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
em_name VARCHAR(50) NOT NULL COMMENT '员工姓名',
age INT DEFAULT 0 COMMENT '年龄',
email VARCHAR(100) COMMENT '邮箱',
department VARCHAR(100) COMMENT '部门',
hire_date DATE COMMENT '入职日期',
salary DECIMAL(10, 2) DEFAULT 0.00 COMMENT '薪资',
version INT DEFAULT 1 COMMENT '乐观锁版本号',
deleted TINYINT DEFAULT 0 COMMENT '逻辑删除标志(0:未删,1:已删)',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT='员工表';

2.引入依赖
XML
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
3.配置多数据源
XML
spring:
# 配置数据源信息
datasource:
dynamic:
# 设置默认的数据源或者数据源组 ,默认值即为master
primary: master
# 严格匹配数据源 ,默认false.true未匹配到指定数据源时抛异常 ,false使用默认数据源
strict: false
datasource:
master:
url: jdbc:mysql://localhost:3306/springbootdemo
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
slave1:
url: jdbc:mysql://localhost:3306/springbootdemo1
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
4.创建IEmployeeService
EmployeeMapper
java
package com.goose.mapper;
import com.goose.entity.Employee;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* <p>
* 员工表 Mapper 接口
* </p>
*
* @author goose
* @since 2025-07-27
*/
@Mapper
@Repository
public interface EmployeeMapper extends BaseMapper<Employee> {}
IEmployeeService
java
package com.goose.service;
import com.goose.entity.Employee;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 员工表 服务类
* </p>
*
* @author goose
* @since 2025-07-27
*/
public interface IEmployeeService extends IService<Employee> {}
EmployeeServiceImpl
java
package com.goose.service.impl;
import com.goose.entity.Employee;
import com.goose.mapper.EmployeeMapper;
import com.goose.service.IEmployeeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 员工表 服务实现类
* </p>
*
* @author goose
* @since 2025-07-27
*/
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {}
5.创建BossService
BossMapper
java
package com.goose.mapper;
import com.goose.entity.Employee;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* <p>
* 员工表 Mapper 接口
* </p>
*
* @author goose
* @since 2025-07-27
*/
@Mapper
@Repository
public interface BossMapper extends BaseMapper<Employee> {}
IBossService
java
package com.goose.service;
import com.goose.entity.Employee;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 员工表 服务类
* </p>
*
* @author goose
* @since 2025-07-27
*/
public interface IBossService extends IService<Employee> {}
BossServiceImpl
java
package com.goose.service.impl;
import com.goose.entity.Employee;
import com.goose.mapper.BossMapper;
import com.goose.mapper.EmployeeMapper;
import com.goose.service.IBossService;
import com.goose.service.IEmployeeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 员工表 服务实现类
* </p>
*
* @author goose
* @since 2025-07-27
*/
@Service
public class BossServiceImpl extends ServiceImpl<BossMapper, Employee> implements IBossService {}
6.测试
java
@SpringBootTest
public class DataSourceTest {
@Autowired
private IBossService bossService;
@Autowired
private IEmployeeService employeeService;
@Test
public void test() {
System.out.println("bossService: " + bossService.getById(1L));
System.out.println("employeeService: " + employeeService.getById(1L));
}
}
输出:
java
bossService: Employee(id=1, emName=张三, age=30, email=zhangsan@example.com, department=研发部, hireDate=2022-05-15, salary=8000.00, version=1, deleted=0, createTime=2025-07-27T16:57:54, updateTime=2025-07-27T16:57:54)
employeeService: Employee(id=1, emName=张三, age=30, email=zhangsan@example.com, department=研发部, hireDate=2022-05-15, salary=8000.00, version=1, deleted=0, createTime=2025-07-27T16:57:43, updateTime=2025-07-27T16:57:43)
7.注意
@DS 注解是MyBatis Plus中用于实现多数据源切换的功能。通过该注解,我们可以直接在方法级别指定使用哪一个数据源,这对于动态选择数据库非常有用,尤其是当你需要在某些业务操作中切换数据源(如:读写分离、按需访问不同数据库等)时。
使用场景
读写分离
在一些系统中,可能有一个主数据库负责写操作,多个副本数据库负责读操作。通过使用 @DS 注解,可以在写操作时切换到主库,读操作时切换到副本库。
多数据源应用
当系统需要同时访问多个数据源时,例如访问不同的数据库实例或数据库类型,使用 @DS 注解可以在不同方法中动态切换数据源。
不同模块的数据源配置
如果你的系统有多个模块,每个模块有自己的数据源配置(如:财务模块、用户模块等),可以通过 @DS 注解在不同模块的服务方法中指定不同的数据源。
(1)使用 @DS 注解切换数据源
假设有一个 UserService 服务类,分别要在不同的方法中使用不同的数据源。
java
import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.stereotype.Service;
@Service
public class UserService {
// 使用主数据源
@DS("primary")
public User getUserFromPrimaryDb(Long userId) {
return userMapper.selectById(userId); // 主数据源的操作
}
// 使用备份数据源
@DS("secondary")
public User getUserFromSecondaryDb(Long userId) {
return userMapper.selectById(userId); // 备份数据源的操作
}
}
(2)控制器层的使用
在控制器层,也可以使用 @DS 注解来切换数据源。
java
import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/getPrimaryUser")
@DS("primary") // 使用主数据源
public User getPrimaryUser(Long userId) {
return userService.getUserFromPrimaryDb(userId);
}
@GetMapping("/getSecondaryUser")
@DS("secondary") // 使用备份数据源
public User getSecondaryUser(Long userId) {
return userService.getUserFromSecondaryDb(userId);
}
}
(3)注意事项
数据源配置
使用 @DS 注解之前,你需要先在 Spring 配置中定义多个数据源,并确保数据源切换机制已经启用。通常,@DS 注解依赖于动态数据源切换框架,如Dynamic DataSource插件。
方法级切换
@DS 注解是直接作用于方法的,因此每个方法都可以选择使用不同的数据源。这非常适用于需要频繁切换数据源的业务逻辑。
事务管理
如果你的方法涉及到多个数据源的操作,注意事务的管理。确保在同一个事务中不能跨数据源操作,因为 MyBatis Plus 默认情况下只会在同一个数据源内进行事务管理。若需要跨数据源事务,可能需要额外的配置或使用分布式事务管理。
性能考虑
频繁的数据源切换可能对性能产生一定影响,特别是在高并发的场景下,确保你在业务上合理使用数据源切换,避免不必要的性能开销。
数据源路由
使用 @DS 注解时,要确保数据源路由逻辑清晰,避免出现不必要的配置混乱或数据源错误。例如,某些操作应该始终使用主数据源(如写操作),而有些查询操作可以使用副本数据源。
默认数据源
如果没有显式指定数据源,系统通常会使用默认数据源。你可以通过配置或代码设置默认数据源,确保没有被 @DS 注解标注的方法也能正常运行。
@DS 注解使得 MyBatis Plus 可以根据业务需求灵活切换不同的数据源。它适用于读写分离、多个数据库并行操作等场景,提供了一种简单的方式来在方法级别上进行数据源的动态切换。
使用时需要注意:
- 正确配置数据源。
- 管理事务的正确性。
- 避免频繁切换数据源导致性能问题。