基于 Spring Boot 的多数据源解决方案,dynamic-datasource-spring-boot-starter 动态多数据源组件使用方法

基于 Spring Boot 的多数据源解决方案,dynamic-datasource-spring-boot-starter 动态多数据源组件使用方法
dynamic-datasource-spring-boot-starter 使用完整指南一、组件简介dynamic-datasource-spring-boot-starter简称dynamic-datasource国内开源多数据源框架 核心特点基于 SpringBoot无侵入通过注解切换数据源支持 主从、多数据源、动态新增数据源、读写分离兼容 Mybatis、Mybatis-Plus、JdbcTemplate支持 HikariCP、Druid 连接池Githubhttps://github.com/baomidou/dynamic-datasource⚠️ 重要提醒不能和 SpringBoot 原生多数据源配置混用全部数据源交由该组件管理。二、版本依赖Mavenpom.xmlxml!-- 最新稳定版适配SpringBoot2 / SpringBoot3 -- dependency groupIdcom.baomidou/groupId artifactIddynamic-datasource-spring-boot-starter/artifactId version4.3.0/version /dependency版本选择参考SpringBoot 2.x4.1.x / 4.2.xSpringBoot 3.xjakarta4.3.0三、基础配置application.yml场景1 个主库 2 个业务库yamlspring: datasource: dynamic: # 设置默认数据源必须存在下面的数据源名称 primary: master # 是否开启严格匹配找不到数据源抛出异常 strict: true datasource: # 主数据源名称master master: url: jdbc:mysql://127.0.0.1:3306/db_master?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver # 从库1 slave1: url: jdbc:mysql://127.0.0.1:3306/db_slave1?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver # 其他业务库 order: url: jdbc:mysql://127.0.0.1:3306/db_order?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver使用 Druid 连接池追加配置yamlspring: datasource: dynamic: druid: initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000四、核心注解使用1. DS 注解核心作用指定当前类 / 方法使用哪个数据源加在类上该类所有方法默认使用此数据源加在方法上优先级高于类注解局部覆盖全局不添加DS默认使用primary: masterjava运行import com.baomidou.dynamic.datasource.annotation.DS; import org.springframework.stereotype.Service; Service // 当前类默认使用slave1数据源 DS(slave1) public class UserService { // 覆盖类注解使用order数据源 DS(order) public void queryOrder() { // 查询order库 } // 使用类上指定的slave1 public void getUser() { // 查询slave1库 } }2. 读写分离模式简化用法配置支持master写、slave多个从库负载均衡yamlspring: datasource: dynamic: primary: master datasource: master: #写库 url: ... slave_1: #读库1 url: ... slave_2: #读库2 url: ...java运行// 自动负载均衡随机选择slave组数据源 DS(slave) public ListUser listUser() { }五、动态创建数据源运行时新增数据源无需重启服务代码动态添加数据源java运行import com.baomidou.dynamic.datasource.DynamicDataSourceContextHolder; import com.baomidou.dynamic.datasource.creator.DataSourceProperty; import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator; import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.sql.DataSource; Component public class DynamicDsUtil { Autowired private DefaultDataSourceCreator dataSourceCreator; Autowired private DynamicDataSourceProvider dynamicDataSourceProvider; /** * 动态新增数据源 */ public void addNewDs(String dsName) { DataSourceProperty property new DataSourceProperty(); property.setUrl(jdbc:mysql://127.0.0.1:3306/db_new); property.setUsername(root); property.setPassword(123456); property.setDriverClassName(com.mysql.cj.jdbc.Driver); DataSource dataSource dataSourceCreator.createDataSource(property); // 添加到动态数据源管理器 dynamicDataSourceProvider.addDataSource(dsName, dataSource); } // 手动切换数据源代码块方式不推荐优先使用优先DS public void manualSwitch() { try { DynamicDataSourceContextHolder.push(order); // 执行业务sql } finally { // 必须清理防止线程污染 DynamicDataSourceContextHolder.clear(); } } }⚠️手动push一定要 finally 清除上下文线程池场景极易数据源串库六、重要注意事项踩坑重点1. 事务坑高频问题同一个事务内无法切换数据源Spring 事务Transactional开启时连接会在事务开始时获取后续DS切换失效。错误示例java运行Transactional public void test() { queryMaster(); // master DS(slave1) querySlave(); // ❌ 不会切换仍然master }解决方案多数据源操作拆分到不同方法不要放在同一个事务如果需要跨数据源事务使用分布式事务Seata AT/TCC。2. AOP 顺序问题框架通过 AOP 实现数据源切换 自定义 AOP 如果顺序不合理会导致DS失效。 建议自定义切面 order -1。3. Mybatis-Plus 分页、Mapper 扫描无需额外改动原生兼容正常使用即可。4. 数据源名称规范名称小写、不要特殊符号区分大小写Slave1≠slave1。5. 多线程场景DynamicDataSourceContextHolder使用 ThreadLocal 新开子线程无法继承父线程数据源子线程需要手动设置DS。七、常用配置完整参数yamlspring: datasource: dynamic: primary: master strict: true # 是否开启p6spy sql日志 p6spy: false datasource: master: url: jdbc:mysql://localhost:3306/db username: root password: 123 driver-class-name: com.mysql.cj.jdbc.Driver八、和其他方案对比dynamic-datasource注解驱动、轻量、动态新增数据源首选方案SpringBoot 原生 AbstractRoutingDataSource需要自己封装不支持动态新增Sharding-JDBC侧重分库分表太重单纯多数据源没必要引入九、常见异常排查Cannot find datasource named xxx名称写错yml 配置缩进错误stricttrue 严格校验切换数据源不生效方法被Transactional包裹内部调用this.xxx ()AOP 无法拦截需要通过上下文获取代理对象调用线程复用导致数据源错乱手动切换数据源必须 clear 上下文如果你需要我可以提供完整可运行 DemoSpringBoot3 MybatisPlus dynamic-datasourceSeata 整合多数据源分布式事务示例从数据库读取数据源配置持久化数据源不用写死 yml