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

MyBatis-Plus多数据源配置与动态切换实战

1. 项目概述

作为一名常年与数据库打交道的Java开发者,我深刻理解多数据源配置在实际项目中的重要性。当系统需要同时连接多个数据库(比如主从分离、分库分表、多租户等场景)时,传统的单数据源方案就显得捉襟见肘。MyBatis-Plus作为MyBatis的增强工具,配合dynamic-datasource-spring-boot-starter组件,可以优雅地解决这个问题。

这个方案的核心价值在于:

  • 零侵入性:无需修改原有MyBatis-Plus代码
  • 动态切换:通过注解即可实现运行时数据源切换
  • 配置简单:Spring Boot风格的配置方式
  • 功能完善:支持事务、读写分离等高级特性

我最近在电商项目中就遇到了这样的需求:需要同时操作业务数据库和日志数据库。经过多种方案对比,最终选择了MyBatis-Plus多数据源方案,实测下来非常稳定。下面就把我的配置过程和踩坑经验分享给大家。

2. 环境准备与依赖配置

2.1 版本匹配要点

在开始之前,版本兼容性是首要考虑的问题。根据我的经验,版本不匹配会导致90%的配置问题。以下是经过验证的稳定版本组合:

<properties> <spring-boot.version>2.7.3</spring-boot.version> <mybatis-plus.version>3.5.1</mybatis-plus.version> <dynamic-datasource.version>3.6.1</dynamic-datasource.version> </properties>

注意:MyBatis-Plus 3.5.x系列与Spring Boot 2.7.x兼容性最好。如果使用Spring Boot 3.x,需要对应升级MyBatis-Plus到最新版。

2.2 核心依赖引入

在pom.xml中添加以下依赖:

<dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring-boot.version}</version> </dependency> <!-- MyBatis-Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!-- 多数据源核心 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>${dynamic-datasource.version}</version> </dependency> <!-- 数据库驱动(以MySQL为例) --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> </dependencies>

3. 多数据源配置详解

3.1 基础配置

在application.yml中配置多数据源:

spring: datasource: dynamic: primary: master # 设置默认数据源 strict: false # 是否严格匹配数据源,默认false datasource: master: url: jdbc:mysql://localhost:3306/master_db?useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver slave: url: jdbc:mysql://localhost:3306/slave_db?useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver

关键参数说明:

  • primary: 指定默认数据源
  • strict: 设为true时,未匹配到数据源会抛出异常
  • 每个数据源的配置与传统单数据源配置相同

3.2 高级配置选项

实际项目中我们通常需要更精细的控制:

spring: datasource: dynamic: hikari: connection-timeout: 30000 max-lifetime: 1800000 max-pool-size: 15 min-idle: 5 datasource: master: # ...其他配置 hikari: pool-name: masterHikariCP slave: # ...其他配置 hikari: pool-name: slaveHikariCP

这样可以为不同数据源单独配置连接池参数,优化性能。

4. 数据源切换实战

4.1 注解式切换

@DS注解是切换数据源的核心:

@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; // 使用master数据源 @DS("master") public void addUser(User user) { userMapper.insert(user); } // 使用slave数据源 @DS("slave") public User getUserById(Long id) { return userMapper.selectById(id); } }

4.2 方法调用链中的注意事项

在方法调用链中,数据源切换遵循以下规则:

  1. 外层方法没有@DS注解时,内层方法注解生效
  2. 外层方法有@DS注解时,内层注解不生效
  3. 事务方法中切换数据源需要特殊处理(后面会讲)
@Service public class OrderServiceImpl implements OrderService { @DS("master") public void createOrder(Order order) { // 这里使用master数据源 orderMapper.insert(order); // 即使方法有@DS("slave"),实际仍使用master updateStatistics(order); } @DS("slave") public void updateStatistics(Order order) { // 由于被createOrder调用,这里的slave不生效 } }

5. 事务处理技巧

5.1 多数据源事务的坑

默认情况下,@Transactional@DS注解一起使用会导致问题:

@DS("master") @Transactional public void transactionalMethod() { // 这里的事务可能不会按预期工作 }

这是因为:

  1. Spring事务基于AOP实现
  2. 事务切面在数据源切换切面之前执行
  3. 导致事务内使用的数据源不正确

5.2 解决方案

方案一:使用DSTransactional注解(推荐)

@DS("master") @DSTransactional public void safeTransactionalMethod() { // 现在事务和数据源都能正确工作 }

方案二:调整切面顺序

@Configuration public class DataSourceConfig { @Bean public DynamicDataSourceAnnotationAdvisor dynamicDataSourceAnnotationAdvisor() { DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(); advisor.setOrder(Ordered.HIGHEST_PRECEDENCE); return advisor; } }

6. 读写分离实战

6.1 配置读写分离

spring: datasource: dynamic: primary: master datasource: master: url: jdbc:mysql://master-host:3306/db username: root password: 123456 slave_1: url: jdbc:mysql://slave1-host:3306/db username: root password: 123456 slave_2: url: jdbc:mysql://slave2-host:3306/db username: root password: 123456 strategy: # 负载均衡策略 slave: round_robin # 轮询

6.2 使用策略

@Service public class UserServiceImpl implements UserService { // 写操作使用master @DS("master") public void addUser(User user) { // insert操作 } // 读操作自动负载均衡到slave @DS("slave") public User getUser(Long id) { // select操作 } }

7. 常见问题排查

7.1 数据源未切换

现象:添加了@DS注解但数据源没有切换

排查步骤

  1. 检查注解是否写在接口上(应该写在实现类)
  2. 检查方法是否是public(非public方法注解不生效)
  3. 检查是否被同类方法调用(自调用注解不生效)

7.2 事务不生效

现象:事务回滚失败

解决方案

  1. 使用@DSTransactional替代@Transactional
  2. 或者确保事务方法的数据源与@DS一致

7.3 性能问题

现象:系统变慢

优化建议

  1. 为不同数据源配置独立的连接池参数
  2. 监控连接泄漏
  3. 合理设置超时时间

8. 最佳实践总结

经过多个项目的实践,我总结了以下经验:

  1. 命名规范:数据源名称要有意义,如order_masterlog_slave
  2. 监控配置:集成Druid监控每个数据源的状态
  3. 压测验证:上线前模拟多数据源并发场景
  4. 降级方案:主库不可用时自动降级到从库
  5. 文档记录:团队内部维护数据源使用规范

最后分享一个实用技巧:在开发环境可以使用H2内存数据库作为备选数据源,避免因数据库服务不可用阻塞开发:

spring: datasource: dynamic: datasource: dev_mem: url: jdbc:h2:mem:testdb username: sa password: driver-class-name: org.h2.Driver
http://www.jsqmd.com/news/1370384/

相关文章:

  • COSCon‘25聚焦开源法律合规与生态发展
  • Qt 实时曲线卡顿优化:从QPainter到OpenGL的3级加速实战
  • 多Agent编排核心技术全解:从模式设计到实战应用
  • 从零实现Transformer:深入理解自注意力机制与PyTorch实战
  • YOLOv3模型训练全流程实战:从数据准备到调优部署
  • 行为克隆实战指南:从模仿学习到自主决策的AI训练方法
  • 华为鸿蒙免费文件加密APP—小羊加密室
  • 网络安全与执法:攻击检测、数据加密与网络取证前沿技术
  • UE引擎关卡流加载技术详解:从流送体积到世界分区的方案选型与实战
  • 朝花夕拾 · C语言 | 调试篇
  • 如何借助数字化工具降低公寓房源空置率并提升运营效率
  • 找靠谱的水溶肥发酵罐实力工厂推荐哪家更合适匠心制罐 - 热点品牌推荐
  • 2026论文AI智能降重工具:11款工具实测谁在“智能”谁在“智障”?
  • Unity游戏实时翻译框架XUnity.AutoTranslator:原理、部署与高阶优化指南
  • 响应式核心:ref 与 reactive
  • SpringBoot电影推荐系统:协同过滤与内容过滤实战
  • 微信视频号直播监控工具wxlivespy:基于Electron与Puppeteer的实时数据采集深度解析
  • 多Agent系统核心协作模式:Lead、Worker与Spawn架构实战解析
  • 筛选厦门性价比高的智能宠物用品源头厂家对接厦门希冠智能(厦门运营中心) - 热点品牌推荐
  • 深度学习GPU性能优化:从监控到分布式训练的全链路实践
  • 8088单板机升级记录2026.8.10
  • 扬帆出海,共同成长:海外留学生校园大使招募!
  • Gazebo仿真中STL转DAE:模型格式转换原理与实战指南
  • Jupyter Notebook运行无响应?从浏览器到内核的完整排查指南
  • 工业时序数据中台架构演进:从 IoTDB + MySQL 到去 DWD 层简化实践
  • 华为鸿蒙经期记录APP—小羊月经
  • Keras与vLLM集成前瞻:简化LLM部署,提升推理性能
  • 2020综合文字版
  • AI音乐生成平台规则收紧:技术解析与开发者应对实践
  • 操作系统安全与端侧 AI 推理部署:部署前防护与拓扑隔离实践