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

Spring Boot多数据源配置实战:Druid+MyBatisPlus整合指南

1. 项目概述

在微服务架构盛行的当下,Spring Boot项目经常需要同时连接多个数据库实例。最近在重构一个老旧的会员系统时,就遇到了需要同时操作MySQL用户库和TiDB交易库的场景。经过多次踩坑,终于实现了基于Druid+MyBatisPlus的稳定多数据源方案。

这个方案最大的特点在于:

  • 完全兼容Spring Boot自动配置特性
  • 支持Druid连接池的各项监控指标
  • 保留MyBatisPlus的所有便捷操作
  • 事务管理清晰可控

特别提醒:多数据源配置中最容易犯的错误就是混淆Mapper接口和XML文件的路径配置,这会导致经典的"Invalid bound statement"异常。

2. 核心配置解析

2.1 依赖管理关键点

在pom.xml中需要特别注意这些依赖项:

<properties> <spring-boot.version>2.7.12</spring-boot.version> <druid.version>1.2.16</druid.version> <mybatis-plus.version>3.5.3.1</mybatis-plus.version> </properties> <dependencies> <!-- 核心starter --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <!-- MyBatisPlus必须单独指定版本 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> <exclusions> <exclusion> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> </exclusion> </exclusions> </dependency> </dependencies>

这里有个重要细节:MyBatisPlus默认使用HikariCP,需要通过exclusions强制移除,否则会与Druid产生冲突。

2.2 配置文件陷阱

application.yml的配置需要特别注意格式:

spring: datasource: master: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/master?useSSL=false username: root password: 123456 druid: initial-size: 5 max-active: 20 validation-query: SELECT 1 slave: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/slave?useSSL=false username: root password: 123456 druid: initial-size: 3 max-active: 15

致命陷阱:第一个数据源用url属性,后续数据源必须用jdbc-url,否则启动时会报"jdbcUrl is required"错误。这是Spring Boot自动配置机制的特殊要求。

3. 数据源配置实战

3.1 主数据源配置

@Configuration @MapperScan(basePackages = "com.example.mapper.master", sqlSessionFactoryRef = "masterSqlSessionFactory") public class MasterDataSourceConfig { @Bean @Primary @ConfigurationProperties("spring.datasource.master") public DataSource masterDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @Primary public SqlSessionFactory masterSqlSessionFactory( @Qualifier("masterDataSource") DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources("classpath:mapper/master/*.xml")); // 关键:注入MyBatisPlus配置 MybatisConfiguration configuration = new MybatisConfiguration(); configuration.setMapUnderscoreToCamelCase(true); configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class); sessionFactory.setConfiguration(configuration); sessionFactory.setPlugins(new MybatisPlusInterceptor()); return sessionFactory.getObject(); } // 其他必要bean... }

3.2 从数据源配置

@Configuration @MapperScan(basePackages = "com.example.mapper.slave", sqlSessionFactoryRef = "slaveSqlSessionFactory") public class SlaveDataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.slave") public DataSource slaveDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean public SqlSessionFactory slaveSqlSessionFactory( @Qualifier("slaveDataSource") DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources("classpath:mapper/slave/*.xml")); // 复用主数据源的MyBatisPlus配置 MybatisConfiguration configuration = new MybatisConfiguration(); configuration.setMapUnderscoreToCamelCase(true); sessionFactory.setConfiguration(configuration); sessionFactory.setPlugins(new MybatisPlusInterceptor()); return sessionFactory.getObject(); } // 其他必要bean... }

4. 事务管理方案

4.1 单数据源事务

直接在Service方法上使用@Transactional即可:

@Service @RequiredArgsConstructor public class OrderService { private final OrderMapper orderMapper; // 主库Mapper @Transactional public void createOrder(Order order) { orderMapper.insert(order); } }

4.2 跨数据源事务

需要引入JTA实现(如Atomikos):

@Bean public JtaTransactionManager transactionManager() { return new JtaTransactionManager(); } // 使用时指定事务管理器 @Transactional(transactionManager = "transactionManager") public void crossDatabaseOperation() { masterMapper.insert(...); slaveMapper.update(...); }

性能警告:分布式事务会显著降低系统吞吐量,建议通过最终一致性方案替代。

5. 监控配置技巧

Druid的监控面板配置:

@Bean public ServletRegistrationBean<StatViewServlet> druidServlet() { ServletRegistrationBean<StatViewServlet> reg = new ServletRegistrationBean<>(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings("/druid/*"); reg.addInitParameter("loginUsername", "admin"); reg.addInitParameter("loginPassword", "admin"); return reg; } @Bean public FilterRegistrationBean<WebStatFilter> filterRegistrationBean() { FilterRegistrationBean<WebStatFilter> reg = new FilterRegistrationBean<>(); reg.setFilter(new WebStatFilter()); reg.addUrlPatterns("/*"); reg.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*"); return reg; }

访问http://localhost:8080/druid即可查看SQL监控、URI监控等数据。

6. 常见问题排查

6.1 Mapper绑定失败

错误现象:

BindingException: Invalid bound statement (not found)

解决方案:

  1. 检查@MapperScan的basePackages是否包含对应Mapper接口
  2. 检查setMapperLocations路径是否包含XML文件
  3. 确认XML中的namespace与Mapper接口全限定名一致

6.2 事务不生效

可能原因:

  1. 方法不是public
  2. 自调用(this.method())
  3. 异常被catch未抛出
  4. 数据库引擎不支持事务(如MyISAM)

6.3 连接泄漏

Druid监控面板查看:

  • activeCount持续增长
  • 检查代码中是否忘记关闭Connection/Statement/ResultSet

7. 性能优化建议

  1. 连接池参数调优:

    druid: min-idle: 5 max-active: 50 max-wait: 3000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000
  2. MyBatisPlus二级缓存:

    @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); interceptor.addInnerInterceptor(new CachingInnerInterceptor()); return interceptor; }
  3. SQL监控慢查询阈值:

    druid: filter: stat: log-slow-sql: true slow-sql-millis: 1000

8. 扩展思考

对于更复杂的多租户场景,可以考虑:

  1. 动态数据源路由(AbstractRoutingDataSource)
  2. Schema级别隔离
  3. MyBatisPlus租户插件

在K8s环境中部署时,建议:

  1. 使用ConfigMap管理数据源配置
  2. 为每个Pod设置合理的连接池大小
  3. 实现健康检查接口监控连接状态
http://www.cnnetsun.cn/news/3578755.html

相关文章:

  • [Released] 4DGS Unity插件——免费的4D高斯溅射实时渲染方案
  • 国际品牌在华战略调整与零售生态变革分析
  • 告别“治而不愈”,中翰软件用AI给数据治理开了一剂“新药”
  • Java企业级AI视频数字人解决方案:JBoltAI核心技术解析
  • C++策略模式实战:从算法封装到架构优化的设计模式指南
  • C++ Pimpl模式高级技巧:编译防火墙、二进制兼容与性能优化
  • 国家中小学智慧教育平台电子课本下载终极指南:5分钟掌握免费离线学习方案
  • Druid实时分析数据库核心原理与应用实践
  • Python错误与异常处理全解析:从语法错误到高级技巧
  • MuMu 5.0模拟器全平台兼容性与性能优化指南
  • 编程入门实战教程:从零基础到项目开发
  • 可对话写歌词的软件:8款AI作词工具真实使用感受分享
  • iPhone 17深度自定义指南:从默认设置到高效个人助手的实战设置
  • TopClaw一键部署指南:OpenClaw中文优化版快速上手
  • AS32S601型抗辐射MCU在分布式太空算力架构中的技术演进与应用前景
  • Unity3D离线安装部署全攻略:从原理到企业级实践
  • 大模型工具在企业知识管理中的深度运用
  • 【NLP】POMDP 与马尔可夫基础
  • 从IBM 1979年观点看计算机在管理决策中的角色演变
  • 第2章_开发环境搭建
  • 【Linux】 基础指令(下)
  • .NET日志系统架构与最佳实践全解析
  • NSK W1507FA 滚珠丝杠技术详解
  • Citrix虚拟化架构解析与1912 LTSR部署实践
  • 地陪APP平台系统开发公司,地陪行业首单转化遇瓶颈?
  • Solidity智能合约开发入门与环境配置指南
  • 宠物社区话题系统搭建,评论点赞实时交互开发实操
  • Codex橙皮书:AI编程工具实战指南与技术解析
  • CEF与SDL整合指南:C++中Web技术与多媒体渲染的融合实践
  • 沈阳正规的软件开发公司哪家可靠