Spring Boot多数据源配置实战:Druid+MyBatisPlus最佳实践
1. 多数据源架构的必要性与挑战在企业级应用开发中多数据源的需求非常普遍。我最近在开发一个电商平台时就遇到了需要同时访问商品数据库和用户数据库的场景。这种架构设计通常出现在以下典型场景中业务数据隔离需求如多租户系统读写分离架构实现异构数据库整合MySQLOracle等分库分表场景下的数据访问使用Spring Boot默认的单数据源配置时我们会发现当尝试配置第二个数据源时Spring的自动配置机制就会失效。这是因为Spring Boot的DataSourceAutoConfiguration类在设计上就是为单数据源场景服务的。关键问题Spring Boot启动时会自动配置第一个找到的数据源而忽略其他数据源配置。这就是为什么我们需要手动管理多个数据源。2. 技术选型为什么是DruidMyBatisPlus组合2.1 Druid连接池的优势在众多数据库连接池中Druid以其强大的监控功能和稳定性脱颖而出。我在压力测试中发现与HikariCP相比Druid在高并发场景下表现更稳定监控全面内置StatFilter提供SQL监控防御SQL注入支持WallFilter性能优异经过阿里双十一验证扩展性强支持自定义过滤器// Druid的典型配置示例 Bean ConfigurationProperties(spring.datasource.druid) public DataSource dataSource() { return DruidDataSourceBuilder.create().build(); }2.2 MyBatisPlus的实用价值MyBatisPlus在简化CRUD操作方面表现出色特别是在多数据源环境下自动分页插件简化开发强大的条件构造器乐观锁等企业级功能与Spring Boot完美集成实际踩坑在多数据源环境下MyBatisPlus的自动注入需要特别注意后面会详细说明如何避免冲突。3. 完整配置实现步骤3.1 项目依赖配置首先需要在pom.xml中添加必要的依赖dependencies !-- Spring Boot Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Druid连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.8/version /dependency !-- MyBatisPlus -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.2/version /dependency !-- 数据库驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.28/version /dependency /dependencies3.2 多数据源YAML配置application.yml中的关键配置spring: datasource: # 主数据源 primary: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/primary_db username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000 # 从数据源 secondary: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/secondary_db username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 3 max-active: 15 min-idle: 3 max-wait: 300003.3 主数据源配置类Configuration MapperScan(basePackages com.example.mapper.primary, sqlSessionFactoryRef primarySqlSessionFactory) public class PrimaryDataSourceConfig { Bean(name primaryDataSource) ConfigurationProperties(prefix spring.datasource.primary) Primary public DataSource primaryDataSource() { return DruidDataSourceBuilder.create().build(); } Bean(name primaryTransactionManager) Primary public DataSourceTransactionManager primaryTransactionManager( Qualifier(primaryDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } Bean(name primarySqlSessionFactory) Primary public SqlSessionFactory primarySqlSessionFactory( Qualifier(primaryDataSource) DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean sessionFactory new MybatisSqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/primary/*.xml)); // MyBatisPlus配置 MybatisConfiguration configuration new MybatisConfiguration(); configuration.setMapUnderscoreToCamelCase(true); sessionFactory.setConfiguration(configuration); return sessionFactory.getObject(); } }3.4 从数据源配置类Configuration MapperScan(basePackages com.example.mapper.secondary, sqlSessionFactoryRef secondarySqlSessionFactory) public class SecondaryDataSourceConfig { Bean(name secondaryDataSource) ConfigurationProperties(prefix spring.datasource.secondary) public DataSource secondaryDataSource() { return DruidDataSourceBuilder.create().build(); } Bean(name secondaryTransactionManager) public DataSourceTransactionManager secondaryTransactionManager( Qualifier(secondaryDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } Bean(name secondarySqlSessionFactory) public SqlSessionFactory secondarySqlSessionFactory( Qualifier(secondaryDataSource) DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean sessionFactory new MybatisSqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/secondary/*.xml)); // MyBatisPlus配置 MybatisConfiguration configuration new MybatisConfiguration(); configuration.setMapUnderscoreToCamelCase(true); sessionFactory.setConfiguration(configuration); return sessionFactory.getObject(); } }4. 关键避坑指南4.1 事务管理陷阱在多数据源环境下Spring的声明式事务管理(Transactional)默认只能作用于主数据源。要实现跨数据源事务需要引入分布式事务解决方案如Seata。// 错误示例这个事务注解只能管理primaryDataSource Transactional public void updateBothDatabases() { primaryMapper.update(...); secondaryMapper.update(...); // 这里出错不会回滚primary的操作 }4.2 MyBatisPlus自动注入冲突MyBatisPlus会自动配置SqlSessionFactory这会与我们的手动配置产生冲突。解决方案是在启动类上排除自动配置SpringBootApplication(exclude { DataSourceAutoConfiguration.class, MybatisPlusAutoConfiguration.class }) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }4.3 连接池配置优化Druid连接池参数需要根据实际业务场景调整参数建议值说明initialSize5-10初始连接数maxActive20-100最大连接数minIdle5-10最小空闲连接maxWait60000获取连接超时时间(ms)timeBetweenEvictionRunsMillis60000检查间隔(ms)4.4 监控界面配置Druid提供了强大的监控功能需要单独配置Bean public ServletRegistrationBeanStatViewServlet druidServlet() { ServletRegistrationBeanStatViewServlet reg new ServletRegistrationBean(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings(/druid/*); // 添加IP白名单 reg.addInitParameter(allow, 127.0.0.1); // 添加登录账号密码 reg.addInitParameter(loginUsername, admin); reg.addInitParameter(loginPassword, admin); return reg; }5. 性能优化建议5.1 SQL监控与分析启用Druid的SQL监控功能可以帮助发现性能瓶颈spring: datasource: druid: filters: stat,wall stat-view-servlet: enabled: true url-pattern: /druid/* login-username: admin login-password: admin5.2 多数据源路由策略对于更复杂的场景可以考虑实现动态数据源路由public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } } // 使用示例 public void someServiceMethod() { DataSourceContextHolder.setDataSourceType(secondary); try { // 这里会使用secondary数据源 secondaryMapper.query(...); } finally { DataSourceContextHolder.clearDataSourceType(); } }5.3 MyBatisPlus插件配置在多数据源环境下配置MyBatisPlus插件需要特别注意Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } // 需要在每个SqlSessionFactory中单独配置 sessionFactory.setPlugins(new Interceptor[]{mybatisPlusInterceptor()});6. 测试验证策略6.1 单元测试配置多数据源环境下的测试类需要特殊处理SpringBootTest TestPropertySource(locations classpath:application-test.yml) AutoConfigureTestDatabase(replace AutoConfigureTestDatabase.Replace.NONE) public class MultiDataSourceTest { Autowired Qualifier(primaryMapper) private UserMapper primaryMapper; Autowired Qualifier(secondaryMapper) private OrderMapper secondaryMapper; Test Transactional(primaryTransactionManager) public void testPrimaryDataSource() { // 测试主数据源 } Test Transactional(secondaryTransactionManager) public void testSecondaryDataSource() { // 测试从数据源 } }6.2 集成测试建议连接泄漏测试确保所有连接都能正确关闭并发测试模拟高并发场景下的连接池表现故障转移测试断开一个数据源验证系统行为性能对比测试与单数据源配置进行性能对比7. 生产环境部署建议7.1 监控指标配置建议监控以下关键指标每个数据源的活跃连接数SQL执行时间分布连接获取等待时间事务成功率7.2 高可用设计对于生产环境建议为每个数据源配置合理的超时参数实现熔断机制防止一个数据源故障影响整个系统考虑使用数据库中间件如ShardingSphere管理复杂场景我在实际项目中遇到过因为未配置合理的超时参数导致系统挂起的情况。后来通过以下配置解决了问题spring: datasource: primary: druid: connect-timeout: 3000 socket-timeout: 10000 secondary: druid: connect-timeout: 3000 socket-timeout: 10000多数据源配置虽然增加了系统复杂性但通过合理的架构设计和参数调优完全可以获得稳定可靠的性能表现。关键在于理解每个配置项背后的原理而不是简单复制粘贴配置。

相关新闻

DDR2/mDDR内存控制器低功耗模式详解:从寄存器配置到实战调试

DDR2/mDDR内存控制器低功耗模式详解:从寄存器配置到实战调试

1. 项目概述:深入理解DDR2/mDDR内存控制器的低功耗管理在嵌入式系统开发,尤其是对功耗敏感的移动设备或电池供电设备中,内存子系统往往是功耗大户。DDR2和mDDR(Mobile DDR)作为曾经的主流内存技术,其控制器…

2026/7/29 1:30:27 阅读更多 →
Dify与n8n对比:AI开发与自动化流程工具选型指南

Dify与n8n对比:AI开发与自动化流程工具选型指南

1. 工具定位与核心差异解析当我们需要在AI开发与自动化流程之间做出工具选择时,Dify和n8n这两个看似都能实现"自动化"的工具,实际上存在着根本性的定位差异。这种差异直接决定了它们的适用场景和技术路线。Dify本质上是一个AI应用开发平台&…

2026/7/28 4:53:33 阅读更多 →
C++函数与运算符重载:从基础原理到实战应用

C++函数与运算符重载:从基础原理到实战应用

1. 项目概述:为什么重载是C的“灵魂”特性之一如果你写过C语言,一定对函数命名这件事感到过一丝“憋屈”。比如,你想写几个函数,功能都是“求和”,但参数类型不同:一个处理两个整数,一个处理两个…

2026/7/27 10:31:56 阅读更多 →

最新新闻

汽车TARA分析实战:从威胁建模到安全需求落地的完整指南

汽车TARA分析实战:从威胁建模到安全需求落地的完整指南

1. 项目概述:为什么TARA分析让工程师又爱又恨?“TARA分析从入门到放弃”,这个标题精准地戳中了无数汽车电子电气工程师的痛点。TARA,全称Threat Analysis and Risk Assessment,即威胁分析与风险评估,是汽车…

2026/7/29 6:38:48 阅读更多 →
零门槛录音转文字实战指南:从设备选择到文本校对

零门槛录音转文字实战指南:从设备选择到文本校对

1. 项目概述:录音转文字技术入门指南录音转文字技术早已不是什么新鲜事物,但真正能零门槛上手的方案却不多见。作为一个在语音处理领域摸爬滚打多年的从业者,我见过太多人在这件事上栽跟头——要么被复杂的软件界面劝退,要么花大价…

2026/7/29 6:38:48 阅读更多 →
深入解析ARM Cortex-M异常与中断:从原理到实战调试

深入解析ARM Cortex-M异常与中断:从原理到实战调试

1. 项目概述:为什么需要深入理解异常与中断?如果你正在使用STM32、GD32或者任何基于ARM Cortex-M3/M4内核的微控制器,那么“异常”和“中断”这两个词一定是你开发路上的常客。它们就像是系统的“神经系统”,负责响应外部世界的各…

2026/7/29 6:38:48 阅读更多 →
永久保存你的QQ空间记忆:GetQzonehistory完整备份方案

永久保存你的QQ空间记忆:GetQzonehistory完整备份方案

永久保存你的QQ空间记忆:GetQzonehistory完整备份方案 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字时代,我们的青春记忆大多存储在QQ空间中&#xff0c…

2026/7/29 6:38:48 阅读更多 →
基于Raft分布式Kv存储:leaderHeartBeatTicker

基于Raft分布式Kv存储:leaderHeartBeatTicker

源码里的准确名字是 leaderHearBeatTicker()。它是 Leader 的周期性调度器: 控制什么时候启动下一轮心跳或日志复制;真正构造 AppendEntries、发送快照和处理各节点复制进度的是 doHeartBeat()。 Raft 要求 Leader 定期向所有 Follower 发送 AppendEntri…

2026/7/29 6:38:48 阅读更多 →
150 行代码,吊打 MyBatis 全家桶

150 行代码,吊打 MyBatis 全家桶

150 行代码,吊打 MyBatis 全家桶 联表才是真实战场,ORM 却在那儿卷单表? 先说结论:两个层次,一次说清 这篇文章有两个层次: 150 行核心代码,直接干翻原生 MyBatis(XML 映射 动态…

2026/7/29 6:37:48 阅读更多 →

日新闻

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:00:23 阅读更多 →
AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础 在上一期「AI编程系列」中,我们学习了如何构建一个基础的 AI 问答系统,通过简单的输入输出让模型回应问题。但现实世界中的 AI 应用往往需要处理更复杂的场景:…

2026/7/29 0:00:23 阅读更多 →
AI智能体开发实战:从工具调用到企业级部署

AI智能体开发实战:从工具调用到企业级部署

1. 从被动问答到主动执行:AI Agent的范式转变过去两年,大语言模型最显著的应用形态是聊天机器人——用户提问,AI回答。但真正的生产力革命发生在2023年下半年:当AI学会主动调用工具完成任务时,生产力工具的历史被彻底改…

2026/7/29 0:00:23 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻