当前位置: 首页 > news >正文

Spring Boot 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 多数据源启动器,它提供了丰富的功能和简便的配置,是实现动态数据源切换的首选方案。

核心特性:

  • 数据源分组: 适用于读写分离、一主多从等复杂场景。
  • 多种切换方式: 支持注解、AOP以及编程方式的灵活切换。
  • 动态数据源: 支持项目启动后动态地增加或移除数据源。
  • 组件集成: 无缝集成 MyBatis-Plus、Quartz、ShardingSphere 等多种组件。
  • 分布式事务: 提供了基于 Seata 的分布式事务解决方案。
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/Shanghaiusername: rootpassword: password123driver-class-name: com.mysql.cj.jdbc.Driverslave_1:url: jdbc:mysql://localhost:3306/db_slave1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: password123driver-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数据源@Overridepublic List<User> getSlaveUsers() {return this.list();}@Overridepublic List<User> getMasterUsers() {// 未使用@DS注解,将使用默认的master数据源return this.list();}
}

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

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

@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate ProductService productService;@Autowiredprivate 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 {@Overrideprotected 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@Primarypublic 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 依赖。无需额外依赖,更为轻量。

选择建议:

  • 对于绝大多数项目,特别是追求开发效率和稳定性的团队,强烈推荐使用 dynamic-datasource-spring-boot-starter
  • 如果项目对依赖有严格控制,或需要实现高度定制化的数据源切换逻辑,可以选择 手动配置 AOP 的方式。

注意事项

  • 事务管理: 在多数据源环境下,需要特别注意事务的一致性。对于单个数据源内的事务,Spring 的 @Transactional 依然有效。但对于跨多个数据源的分布式事务,则需要引入如 Seata 等分布式事务解决方案。
  • AOP顺序: 如果同时使用了 @Transactional@DS 注解,需要注意 AOP 的执行顺序,确保数据源切换在事务开启之前执行。

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

http://www.dtcms.com/a/351724.html

相关文章:

  • 【CVE-2025-5419】(内附EXP) Google Chrome 越界读写漏洞【内附EXP】
  • Kafka面试精讲 Day 1:Kafka核心概念与分布式架构
  • Elasticsearch中的协调节点
  • 详解kafka基础(一)
  • JavaScript常用的算法详解
  • Cherry-pick冲突与Git回滚
  • Oracle跟踪及分析方法
  • 力扣100+补充大完结
  • MySql 事务 锁
  • 推荐系统学习笔记(十四)-粗排三塔模型
  • 庖丁解牛:深入解析Oracle SQL语言的四大分类——DML、DDL、DCL、TCL
  • KubeBlocks for Oracle 容器化之路
  • 高校党建系统设计与实现(代码+数据库+LW)
  • 从零开始的 Docker 之旅
  • HIVE的高频面试UDTF函数
  • 【软考论文】论面向对象建模方法(动态、静态)
  • 无人机倾斜摄影农田航线规划
  • HTML应用指南:利用GET请求获取中国银行人民币存款利率数据
  • SciPy科学计算与应用:SciPy线性代数模块入门-矩阵运算与应用
  • 精确位置定位,AR交互助力高效作业流程​
  • 余承东:鸿蒙智行累计交付突破90万辆
  • 机器人视频感知架构深度解析:7条技术法则,打造低延迟实时感知与交互
  • 【ROS2】 忽略局域网多机通信导致数据接收的bug
  • 天气查询小程序项目报告
  • iOS 审核 4.3a【二进制加固】
  • Spring MVC 全解析:从核心原理到 SSM 整合实战 (附完整源码)
  • leetcode-python-383赎金信
  • 深度学习----由手写数字识别案例来认识PyTorch框架
  • 构建AI智能体:十四、从“计算”到“洞察”:AI大模型如何让时间序列数据“开口说话”
  • version GLIBCXX_3.4.30‘ not found (required by cmake)