news 2026/7/22 5:40:49

Spring Boot多数据源配置实战:Druid+MyBatisPlus最佳实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot多数据源配置实战:Druid+MyBatisPlus最佳实践

1. 多数据源架构的必要性与挑战

在企业级应用开发中,多数据源的需求非常普遍。我最近在开发一个电商平台时,就遇到了需要同时访问商品数据库和用户数据库的场景。这种架构设计通常出现在以下典型场景中:

  • 业务数据隔离需求(如多租户系统)
  • 读写分离架构实现
  • 异构数据库整合(MySQL+Oracle等)
  • 分库分表场景下的数据访问

使用Spring Boot默认的单数据源配置时,我们会发现当尝试配置第二个数据源时,Spring的自动配置机制就会失效。这是因为Spring Boot的DataSourceAutoConfiguration类在设计上就是为单数据源场景服务的。

关键问题:Spring Boot启动时会自动配置第一个找到的数据源,而忽略其他数据源配置。这就是为什么我们需要手动管理多个数据源。

2. 技术选型:为什么是Druid+MyBatisPlus组合

2.1 Druid连接池的优势

在众多数据库连接池中,Druid以其强大的监控功能和稳定性脱颖而出。我在压力测试中发现,与HikariCP相比,Druid在高并发场景下表现更稳定:

  1. 监控全面:内置StatFilter提供SQL监控
  2. 防御SQL注入:支持WallFilter
  3. 性能优异:经过阿里双十一验证
  4. 扩展性强:支持自定义过滤器
// 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> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency> <!-- MyBatisPlus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <!-- 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> </dependencies>

3.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: 30000

3.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 ServletRegistrationBean<StatViewServlet> druidServlet() { ServletRegistrationBean<StatViewServlet> 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: admin

5.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 集成测试建议

  1. 连接泄漏测试:确保所有连接都能正确关闭
  2. 并发测试:模拟高并发场景下的连接池表现
  3. 故障转移测试:断开一个数据源,验证系统行为
  4. 性能对比测试:与单数据源配置进行性能对比

7. 生产环境部署建议

7.1 监控指标配置

建议监控以下关键指标:

  • 每个数据源的活跃连接数
  • SQL执行时间分布
  • 连接获取等待时间
  • 事务成功率

7.2 高可用设计

对于生产环境,建议:

  1. 为每个数据源配置合理的超时参数
  2. 实现熔断机制,防止一个数据源故障影响整个系统
  3. 考虑使用数据库中间件如ShardingSphere管理复杂场景

我在实际项目中遇到过因为未配置合理的超时参数导致系统挂起的情况。后来通过以下配置解决了问题:

spring: datasource: primary: druid: connect-timeout: 3000 socket-timeout: 10000 secondary: druid: connect-timeout: 3000 socket-timeout: 10000

多数据源配置虽然增加了系统复杂性,但通过合理的架构设计和参数调优,完全可以获得稳定可靠的性能表现。关键在于理解每个配置项背后的原理,而不是简单复制粘贴配置。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 5:39:57

FT891与SDR切换器一线通方案:硬件集成与抗干扰实战

那天晚上&#xff0c;我正调试着新到的 Yaesu FT-891 短波电台和手头的 SDR&#xff08;软件定义无线电&#xff09;设备&#xff0c;桌上摊着好几根线——电台要供电&#xff0c;SDR 要供电&#xff0c;PTT&#xff08;Push-to-Talk&#xff09;信号还要单独接。电源线、数据线…

作者头像 李华
网站建设 2026/7/22 5:39:33

6款高效免费软件推荐:办公设计全搞定

1. 前言&#xff1a;免费软件的实用价值在这个数字化时代&#xff0c;优质软件能极大提升我们的工作效率和生活品质。但很多专业软件价格昂贵&#xff0c;对普通用户来说负担不小。今天我要分享6款完全免费的实用软件&#xff0c;它们不仅功能强大&#xff0c;而且能解决日常工…

作者头像 李华
网站建设 2026/7/22 5:37:43

Python3.8与RobotFramework环境搭建及兼容性解决方案

1. Python3.8与RobotFramework环境搭建实录去年接手一个遗留项目时&#xff0c;发现团队还在用Python3.8RobotFramework3.2的老旧组合。本想直接升级到最新版&#xff0c;结果发现项目中有大量基于旧版本开发的测试用例。经过多次尝试&#xff0c;终于摸索出一套稳定的安装方案…

作者头像 李华
网站建设 2026/7/22 5:36:00

AI视觉算法在矿山皮带异物识别与跑偏预警中的应用

1. 矿山皮带异物识别与跑偏预警的技术挑战矿山运输皮带系统是物料输送的核心设备&#xff0c;其安全稳定运行直接关系到生产效率和人员安全。传统的人工巡检方式存在三大痛点&#xff1a;一是皮带运行环境复杂&#xff0c;粉尘、振动等因素导致人工检测准确率不足60%&#xff1…

作者头像 李华
网站建设 2026/7/22 5:32:47

Video2x视频增强工具:基于GAN的超分辨率与补帧技术详解

1. 项目概述&#xff1a;Video2x视频增强工具解析这个在GitHub上狂揽1.7万星标的开源项目&#xff0c;本质上是一个基于深度学习的视频处理工具链。它最核心的能力是通过神经网络算法&#xff0c;将低分辨率、模糊的老旧视频素材&#xff0c;智能提升至高清甚至4K画质&#xff…

作者头像 李华
网站建设 2026/7/22 5:28:57

毕业设计论文写作痛点与智能解决方案

1. 毕业设计论文写作痛点解析每年毕业季&#xff0c;数以百万计的大学生面临同样的困境——如何在有限时间内完成高质量的毕业设计论文。传统论文写作流程存在三大核心痛点&#xff1a;时间管理失控&#xff1a;从开题到答辩通常只有3-6个月&#xff0c;但学生往往前松后紧&…

作者头像 李华