java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot mybatis-plus多数据源配置

SpringBoot+mybatis-plus实现多数据源配置的详细步骤

作者:冰糖心书房

在日益复杂的业务场景中,单一数据源往往难以满足微服务架构下的多元化需求,文将详细介绍两种主流的 MyBatis-Plus 多数据源配置方式,大家可以根据需要进行选择

MyBatis-Plus 多数据源配置详解

在日益复杂的业务场景中,单一数据源往往难以满足微服务架构下的多元化需求,例如数据库的读写分离、分库分表、以及连接不同业务模块的独立数据库等。MyBatis-Plus 作为一款广受欢迎的持久层框架,通过其强大的扩展性,为开发者提供了灵活便捷的多数据源配置方案。

本文将详细介绍两种主流的 MyBatis-Plus 多数据源配置方式:一种是官方推荐且广为使用的 dynamic-datasource-spring-boot-starter 插件,另一种是基于 AOP(面向切面编程)的手动配置方案,以帮助开发者根据项目需求做出最优选择。

推荐方案:使用dynamic-datasource-spring-boot-starter

dynamic-datasource-spring-boot-starter 是一个由 MyBatis-Plus 团队成员开源的 Spring Boot 多数据源启动器,它提供了丰富的功能和简便的配置,是实现动态数据源切换的首选方案。

核心特性:

1. 引入依赖

根据您的 Spring Boot 版本,在 pom.xml 文件中引入相应的依赖:

Spring Boot 2.x:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.2</version> <!-- 请使用最新版本 -->
</dependency>

Spring Boot 3.x:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
    <version>4.2.0</version> <!-- 请使用最新版本 -->
</dependency>

2. 配置文件application.yml

在配置文件中定义多个数据源,并指定主数据源。

spring:
  datasource:
    dynamic:
      primary: master # 设置默认的数据源
      strict: false # 设置为true时,未匹配到数据源会报错,设置为false则使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/db_master?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
          username: root
          password: password123
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_1:
          url: jdbc:mysql://localhost:3306/db_slave1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
          username: root
          password: password123
          driver-class-name: com.mysql.cj.jdbc.Driver

3. 数据源切换方式

a. 注解方式(@DS)

@DS 注解是切换数据源最便捷的方式,可以作用于类或方法上。方法上的注解优先级高于类上的注解。

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @DS("slave_1") // 指定使用slave_1数据源
    @Override
    public List<User> getSlaveUsers() {
        return this.list();
    }

    @Override
    public List<User> getMasterUsers() {
        // 未使用@DS注解,将使用默认的master数据源
        return this.list();
    }
}

b. 编程方式(手动切换)

在某些复杂的业务场景下,需要在代码中动态决定使用哪个数据源,此时可以使用 DynamicDataSourceContextHolder 进行手动切换。

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private ProductService productService;

    @Autowired
    private StockService stockService;

    public void createOrder(String productId, int amount) {
        // 查询商品信息,切换到slave数据源
        DynamicDataSourceContextHolder.push("slave_1");
        Product product = productService.getById(productId);
        DynamicDataSourceContextHolder.clear(); // 每次使用后必须清空

        // 扣减库存,切换到master数据源
        DynamicDataSourceContextHolder.push("master");
        stockService.deduct(productId, amount);
        DynamicDataSourceContextHolder.clear();

        // ... 创建订单等操作,使用默认数据源
    }
}

手动配置方案:基于 AOP 实现

对于希望拥有更高自由度或不愿引入额外依赖的开发者,可以采用自定义注解和 AOP 的方式手动实现动态数据源切换。其核心原理是利用 Spring 提供的 AbstractRoutingDataSource 类。

1. 添加 AOP 依赖

pom.xml 中确保已引入 AOP 相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 自定义数据源注解

创建一个注解,用于在需要切换数据源的方法上进行标识。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String value();
}

3. 创建动态数据源上下文

使用 ThreadLocal 存储当前线程需要使用的数据源名称,以确保线程安全。

public class DynamicDataSourceContextHolder {

    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    public static void setDataSourceKey(String key) {
        CONTEXT_HOLDER.set(key);
    }

    public static String getDataSourceKey() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearDataSourceKey() {
        CONTEXT_HOLDER.remove();
    }
}

4. 实现AbstractRoutingDataSource

这是实现动态数据源的核心,通过重写 determineCurrentLookupKey 方法,从 DynamicDataSourceContextHolder 中获取当前数据源的 key。

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceKey();
    }
}

5. 配置数据源

通过 Java Config 的方式配置多个数据源,并将它们注入到 DynamicDataSource 中。

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", masterDataSource);
        targetDataSources.put("slave", slaveDataSource);

        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(masterDataSource);
        return dataSource;
    }
}

并在 application.yml 中配置相应的数据源信息:

spring:
  datasource:
    master:
      url: jdbc:mysql://localhost:3306/db_master...
      # ...
    slave:
      url: jdbc:mysql://localhost:3306/db_slave1...
      # ...

6. 编写 AOP 切面

创建切面,拦截带有 @DataSource 注解的方法,在方法执行前后设置和清除数据源 key。

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(com.example.annotation.DataSource)")
    public void dataSourcePointCut() {
    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        DataSource dataSource = method.getAnnotation(DataSource.class);
        if (dataSource != null) {
            DynamicDataSourceContextHolder.setDataSourceKey(dataSource.value());
        }
        try {
            return point.proceed();
        } finally {
            DynamicDataSourceContextHolder.clearDataSourceKey();
        }
    }
}

方案对比与选择

特性dynamic-datasource-spring-boot-starter手动配置 AOP
易用性高,开箱即用,配置简单。中,需要手动编写较多代码。
功能丰富度高,支持分组、动态数据源、分布式事务等。低,仅实现基础的切换功能。
灵活性高,支持多种切换方式。高,完全自定义实现,可控性强。
依赖引入额外 starter 依赖。无需额外依赖,更为轻量。

选择建议:

注意事项

通过以上两种方案的介绍,开发者可以根据自身项目的实际需求和团队的技术栈,选择最合适的方式来配置和管理 MyBatis-Plus 的多数据源,从而构建出更加健壮和可扩展的应用系统。

到此这篇关于SpringBoot+mybatis-plus实现多数据源配置的详细步骤的文章就介绍到这了,更多相关SpringBoot mybatis-plus多数据源配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文