Mybatis Plus 多数据源

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 可以根据业务需求灵活切换不同的数据源。它适用于读写分离、多个数据库并行操作等场景,提供了一种简单的方式来在方法级别上进行数据源的动态切换。

使用时需要注意:

  1. 正确配置数据源。
  2. 管理事务的正确性。
  3. 避免频繁切换数据源导致性能问题。
相关推荐
snakeshe10104 分钟前
Java依赖管理演进史:从Classpath地狱到Maven救赎
后端
愿你天黑有灯下雨有伞4 分钟前
Spring Boot集成RabbitMQ终极指南:从配置到高级消息处理
spring boot·rabbitmq·java-rabbitmq
snakeshe10105 分钟前
HTTP协议:互联网通信的基石与核心技术解析
后端
snakeshe10107 分钟前
骨架与能力:一文吃透 Java 抽象类、接口、内部类及实战模式
后端
snakeshe10107 分钟前
命令行完全指南:从内核原理到开发实战
后端
回家路上绕了弯9 分钟前
追求代码简洁之道:我的实践与感悟
后端·代码规范
手握风云-11 分钟前
JavaEE初阶第十二期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(十)
java·开发语言·java-ee
NicolasCage13 分钟前
C语言指针Pointers
c++·后端
JohnYan14 分钟前
Bun技术评估 - 16 Package Manager
javascript·后端·bun
盖世英雄酱5813618 分钟前
加了锁,加了事务 还是重复报名❓
java·数据库·后端