SpringBootMyBatis多数据源实战从本地到云端MySQL的完整配置流程当企业级应用需要同时处理开发环境与生产环境数据时多数据源配置成为刚需。想象这样一个场景开发者在本地调试时需要操作测试数据库同时又要将处理结果同步到云端的生产数据库。这种跨环境数据流转的需求正是多数据源技术大显身手的时刻。本文将带你深入SpringBootMyBatis多数据源配置的完整流程从基础配置到性能优化再到生产环境实战技巧。不同于简单的配置示例我们会重点解决实际开发中的三个核心痛点如何优雅管理不同环境的配置差异、如何优化Druid连接池参数提升性能以及如何避免多环境切换时的常见坑点。1. 环境准备与依赖配置在开始多数据源配置前需要确保项目基础环境就绪。不同于单数据源项目多数据源配置对依赖版本和项目结构有更严格的要求。首先检查pom.xml中的关键依赖版本兼容性。以下是我们验证过的稳定版本组合dependencies !-- SpringBoot Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId version2.7.0/version /dependency !-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.28/version scoperuntime/scope /dependency !-- MyBatis核心 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.9/version /dependency !-- MyBatis-Spring整合 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.7/version /dependency !-- Druid连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.8/version /dependency /dependencies提示使用druid-spring-boot-starter而非原生Druid依赖可以简化后续配置项目结构也需要特别规划。推荐采用以下目录布局src/main/java ├── config │ ├── DevDataSourceConfig.java │ └── ProdDataSourceConfig.java ├── mapper │ ├── dev │ └── prod └── resources ├── mapper │ ├── dev │ └── prod └── application.yml这种结构清晰隔离了不同数据源的配置和映射文件避免了后续维护时的混乱。2. 多数据源核心配置2.1 YAML配置文件设计application.yml的配置是多数据源的基础。我们采用环境隔离的配置方式既保证安全性又便于维护spring: profiles: active: activatedProperties # Maven过滤不同环境配置 --- # 开发环境配置 spring: profiles: dev datasource: dev: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/dev_db?useSSLfalseallowPublicKeyRetrievaltrue username: dev_user password: dev123 type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000 validation-query: SELECT 1 test-while-idle: true prod: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://prod-db.example.com:3306/prod_db?useSSLtruerequireSSLtrue username: ${PROD_DB_USER} password: ${PROD_DB_PASS} type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 10 max-active: 50 min-idle: 10 max-wait: 30000 validation-query: SELECT 1 test-on-borrow: true --- # 生产环境配置 spring: profiles: prod datasource: # 生产环境配置与开发环境类似但参数不同 # 此处省略具体配置...关键配置要点使用---分隔不同环境的配置生产环境密码采用环境变量注入${PROD_DB_USER}开发与生产环境采用不同的Druid连接池参数SSL配置根据环境自动切换2.2 Java配置类实现每个数据源需要独立的配置类。以下是生产环境数据源的完整配置示例Configuration MapperScan( basePackages com.example.mapper.prod, sqlSessionFactoryRef prodSqlSessionFactory ) public class ProdDataSourceConfig { Bean(name prodDataSource) ConfigurationProperties(spring.datasource.prod) public DataSource prodDataSource() { return DruidDataSourceBuilder.create().build(); } Bean(name prodTransactionManager) public DataSourceTransactionManager prodTransactionManager( Qualifier(prodDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } Bean(name prodSqlSessionFactory) public SqlSessionFactory prodSqlSessionFactory( Qualifier(prodDataSource) DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/prod/*.xml)); // 自定义MyBatis配置 org.apache.ibatis.session.Configuration configuration new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); sessionFactory.setConfiguration(configuration); return sessionFactory.getObject(); } Bean(name prodSqlSessionTemplate) public SqlSessionTemplate prodSqlSessionTemplate( Qualifier(prodSqlSessionFactory) SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }开发环境配置类结构类似主要区别在于MapperScan的basePackages指向开发环境mapper包Bean名称前缀改为dev数据源配置路径指向spring.datasource.dev注意务必在其中一个配置类中将某个数据源标记为Primary这是解决Consider marking one of the beans as Primary错误的关键3. 高级配置与优化3.1 Druid连接池深度调优Druid作为生产级连接池提供了丰富的监控和优化参数。以下是针对高并发场景的优化配置示例spring: datasource: prod: druid: # 连接池大小配置 initial-size: 10 max-active: 100 min-idle: 20 max-wait: 5000 # 监控统计相关 filters: stat,wall,slf4j stat-view-servlet: enabled: true url-pattern: /druid/* login-username: admin login-password: admin # 防御SQL注入 wall: config: multi-statement-allow: true none-base-statement-allow: false # 性能优化 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 test-while-idle: true test-on-borrow: false test-on-return: false关键优化点说明参数推荐值作用说明max-active根据服务器配置最大连接数建议不超过数据库max_connections的80%time-between-eviction-runs-millis60000检测间隔(ms)过长可能导致连接泄漏min-evictable-idle-time-millis300000最小空闲时间(ms)避免频繁创建销毁连接filtersstat,wall开启监控和SQL防火墙功能3.2 多环境切换策略在实际项目中我们经常需要在不同环境间切换。以下是三种经过验证的方案对比方案一Profile隔离# 启动时指定环境 java -jar app.jar --spring.profiles.activeprod方案二Maven Profile过滤profiles profile iddev/id activation activeByDefaulttrue/activeByDefault /activation properties activatedPropertiesdev/activatedProperties /properties /profile profile idprod/id properties activatedPropertiesprod/activatedProperties /properties /profile /profiles方案三配置中心动态切换RefreshScope Configuration public class DynamicDataSourceConfig { // 结合Nacos/Apollo等配置中心实现运行时切换 }方案选择建议小型项目方案一或方案二中大型项目方案三需要热更新配置必须方案三4. 实战问题排查与解决方案4.1 常见错误与修复问题一循环依赖导致启动失败Error creating bean with name dataSourceInitializerPostProcessor: Requested bean is currently in creation: Is there an unresolvable circular reference?解决方案确保只有一个数据源标记为Primary在启动类添加排除自动配置SpringBootApplication(exclude { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class })问题二MyBatis映射文件冲突org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决方案确保每个Mapper接口有对应的XML文件检查MapperScan的basePackages路径是否正确验证XML文件中的namespace与Mapper接口全限定名一致4.2 性能监控配置集成Druid监控面板可以实时观察多数据源运行状态添加监控Servlet配置Bean public ServletRegistrationBeanStatViewServlet druidServlet() { ServletRegistrationBeanStatViewServlet reg new ServletRegistrationBean(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings(/druid/*); reg.addInitParameter(loginUsername, admin); reg.addInitParameter(loginPassword, admin); return reg; }添加过滤器配置Bean public FilterRegistrationBeanWebStatFilter filterRegistrationBean() { FilterRegistrationBeanWebStatFilter reg new FilterRegistrationBean(); reg.setFilter(new WebStatFilter()); reg.addUrlPatterns(/*); reg.addInitParameter(exclusions, *.js,*.gif,*.jpg,*.css,/druid/*); return reg; }访问http://localhost:8080/druid即可查看监控数据包括数据源活跃连接数SQL执行统计慢SQL记录URI访问监控5. 云端部署特别注意事项当应用部署到云环境时多数据源配置需要额外关注以下方面网络连接优化prod: jdbc-url: jdbc:mysql://prod-db.example.com:3306/db? useSSLtrue requireSSLtrue verifyServerCertificatefalse useCompressiontrue socketTimeout30000 connectTimeout5000连接池参数调整druid: # 云数据库通常有连接数限制 max-active: 50 # 网络不稳定需要更积极的保活 keep-alive: true keep-alive-between-time-millis: 30000健康检查配置Bean public DataSourceHealthContributor dataSourceHealthContributor( MapString, DataSource dataSources) { var builder new CompositeHealthContributor.Builder(); dataSources.forEach((name, dataSource) - builder.addContributor(name DataSource, DataSourceHealthIndicator(dataSource))); return builder.build(); }云端部署的黄金法则总是假设网络会不稳定连接会断开超时会发生。配置中每个参数都应该为这种场景做好准备。
SpringBoot+MyBatis多数据源实战:从本地到云端MySQL的完整配置流程
SpringBootMyBatis多数据源实战从本地到云端MySQL的完整配置流程当企业级应用需要同时处理开发环境与生产环境数据时多数据源配置成为刚需。想象这样一个场景开发者在本地调试时需要操作测试数据库同时又要将处理结果同步到云端的生产数据库。这种跨环境数据流转的需求正是多数据源技术大显身手的时刻。本文将带你深入SpringBootMyBatis多数据源配置的完整流程从基础配置到性能优化再到生产环境实战技巧。不同于简单的配置示例我们会重点解决实际开发中的三个核心痛点如何优雅管理不同环境的配置差异、如何优化Druid连接池参数提升性能以及如何避免多环境切换时的常见坑点。1. 环境准备与依赖配置在开始多数据源配置前需要确保项目基础环境就绪。不同于单数据源项目多数据源配置对依赖版本和项目结构有更严格的要求。首先检查pom.xml中的关键依赖版本兼容性。以下是我们验证过的稳定版本组合dependencies !-- SpringBoot Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId version2.7.0/version /dependency !-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.28/version scoperuntime/scope /dependency !-- MyBatis核心 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.9/version /dependency !-- MyBatis-Spring整合 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.7/version /dependency !-- Druid连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.8/version /dependency /dependencies提示使用druid-spring-boot-starter而非原生Druid依赖可以简化后续配置项目结构也需要特别规划。推荐采用以下目录布局src/main/java ├── config │ ├── DevDataSourceConfig.java │ └── ProdDataSourceConfig.java ├── mapper │ ├── dev │ └── prod └── resources ├── mapper │ ├── dev │ └── prod └── application.yml这种结构清晰隔离了不同数据源的配置和映射文件避免了后续维护时的混乱。2. 多数据源核心配置2.1 YAML配置文件设计application.yml的配置是多数据源的基础。我们采用环境隔离的配置方式既保证安全性又便于维护spring: profiles: active: activatedProperties # Maven过滤不同环境配置 --- # 开发环境配置 spring: profiles: dev datasource: dev: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/dev_db?useSSLfalseallowPublicKeyRetrievaltrue username: dev_user password: dev123 type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000 validation-query: SELECT 1 test-while-idle: true prod: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://prod-db.example.com:3306/prod_db?useSSLtruerequireSSLtrue username: ${PROD_DB_USER} password: ${PROD_DB_PASS} type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 10 max-active: 50 min-idle: 10 max-wait: 30000 validation-query: SELECT 1 test-on-borrow: true --- # 生产环境配置 spring: profiles: prod datasource: # 生产环境配置与开发环境类似但参数不同 # 此处省略具体配置...关键配置要点使用---分隔不同环境的配置生产环境密码采用环境变量注入${PROD_DB_USER}开发与生产环境采用不同的Druid连接池参数SSL配置根据环境自动切换2.2 Java配置类实现每个数据源需要独立的配置类。以下是生产环境数据源的完整配置示例Configuration MapperScan( basePackages com.example.mapper.prod, sqlSessionFactoryRef prodSqlSessionFactory ) public class ProdDataSourceConfig { Bean(name prodDataSource) ConfigurationProperties(spring.datasource.prod) public DataSource prodDataSource() { return DruidDataSourceBuilder.create().build(); } Bean(name prodTransactionManager) public DataSourceTransactionManager prodTransactionManager( Qualifier(prodDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } Bean(name prodSqlSessionFactory) public SqlSessionFactory prodSqlSessionFactory( Qualifier(prodDataSource) DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/prod/*.xml)); // 自定义MyBatis配置 org.apache.ibatis.session.Configuration configuration new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); sessionFactory.setConfiguration(configuration); return sessionFactory.getObject(); } Bean(name prodSqlSessionTemplate) public SqlSessionTemplate prodSqlSessionTemplate( Qualifier(prodSqlSessionFactory) SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }开发环境配置类结构类似主要区别在于MapperScan的basePackages指向开发环境mapper包Bean名称前缀改为dev数据源配置路径指向spring.datasource.dev注意务必在其中一个配置类中将某个数据源标记为Primary这是解决Consider marking one of the beans as Primary错误的关键3. 高级配置与优化3.1 Druid连接池深度调优Druid作为生产级连接池提供了丰富的监控和优化参数。以下是针对高并发场景的优化配置示例spring: datasource: prod: druid: # 连接池大小配置 initial-size: 10 max-active: 100 min-idle: 20 max-wait: 5000 # 监控统计相关 filters: stat,wall,slf4j stat-view-servlet: enabled: true url-pattern: /druid/* login-username: admin login-password: admin # 防御SQL注入 wall: config: multi-statement-allow: true none-base-statement-allow: false # 性能优化 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 test-while-idle: true test-on-borrow: false test-on-return: false关键优化点说明参数推荐值作用说明max-active根据服务器配置最大连接数建议不超过数据库max_connections的80%time-between-eviction-runs-millis60000检测间隔(ms)过长可能导致连接泄漏min-evictable-idle-time-millis300000最小空闲时间(ms)避免频繁创建销毁连接filtersstat,wall开启监控和SQL防火墙功能3.2 多环境切换策略在实际项目中我们经常需要在不同环境间切换。以下是三种经过验证的方案对比方案一Profile隔离# 启动时指定环境 java -jar app.jar --spring.profiles.activeprod方案二Maven Profile过滤profiles profile iddev/id activation activeByDefaulttrue/activeByDefault /activation properties activatedPropertiesdev/activatedProperties /properties /profile profile idprod/id properties activatedPropertiesprod/activatedProperties /properties /profile /profiles方案三配置中心动态切换RefreshScope Configuration public class DynamicDataSourceConfig { // 结合Nacos/Apollo等配置中心实现运行时切换 }方案选择建议小型项目方案一或方案二中大型项目方案三需要热更新配置必须方案三4. 实战问题排查与解决方案4.1 常见错误与修复问题一循环依赖导致启动失败Error creating bean with name dataSourceInitializerPostProcessor: Requested bean is currently in creation: Is there an unresolvable circular reference?解决方案确保只有一个数据源标记为Primary在启动类添加排除自动配置SpringBootApplication(exclude { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class })问题二MyBatis映射文件冲突org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决方案确保每个Mapper接口有对应的XML文件检查MapperScan的basePackages路径是否正确验证XML文件中的namespace与Mapper接口全限定名一致4.2 性能监控配置集成Druid监控面板可以实时观察多数据源运行状态添加监控Servlet配置Bean public ServletRegistrationBeanStatViewServlet druidServlet() { ServletRegistrationBeanStatViewServlet reg new ServletRegistrationBean(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings(/druid/*); reg.addInitParameter(loginUsername, admin); reg.addInitParameter(loginPassword, admin); return reg; }添加过滤器配置Bean public FilterRegistrationBeanWebStatFilter filterRegistrationBean() { FilterRegistrationBeanWebStatFilter reg new FilterRegistrationBean(); reg.setFilter(new WebStatFilter()); reg.addUrlPatterns(/*); reg.addInitParameter(exclusions, *.js,*.gif,*.jpg,*.css,/druid/*); return reg; }访问http://localhost:8080/druid即可查看监控数据包括数据源活跃连接数SQL执行统计慢SQL记录URI访问监控5. 云端部署特别注意事项当应用部署到云环境时多数据源配置需要额外关注以下方面网络连接优化prod: jdbc-url: jdbc:mysql://prod-db.example.com:3306/db? useSSLtrue requireSSLtrue verifyServerCertificatefalse useCompressiontrue socketTimeout30000 connectTimeout5000连接池参数调整druid: # 云数据库通常有连接数限制 max-active: 50 # 网络不稳定需要更积极的保活 keep-alive: true keep-alive-between-time-millis: 30000健康检查配置Bean public DataSourceHealthContributor dataSourceHealthContributor( MapString, DataSource dataSources) { var builder new CompositeHealthContributor.Builder(); dataSources.forEach((name, dataSource) - builder.addContributor(name DataSource, DataSourceHealthIndicator(dataSource))); return builder.build(); }云端部署的黄金法则总是假设网络会不稳定连接会断开超时会发生。配置中每个参数都应该为这种场景做好准备。