SpringBoot多数据源配置,看这一篇就够了
2026/9/18 19:16:42 网站建设 项目流程

做业务开发,迟早会遇到一个需求:一个项目要连多个数据库。可能是读写分离,主库写、从库读;可能是业务隔离,订单库和用户库分开;也可能是历史遗留,老系统数据要同步查询。这时候,SpringBoot多数据源配置就成了绕不开的坎。网上的教程要么太浅,要么互相矛盾,今天这篇,把原理、实现和坑一次讲透。

方案怎么选?

多数据源实现方式主要有三种:

第一种,手动配置多套DataSource + SqlSessionFactory。最原始,也最灵活。每个数据源独立配置连接池、事务管理器、Mapper扫描路径。缺点是代码量大,新增数据源要改配置类。

第二种,使用AbstractRoutingDataSource + AOP动态切换。这是Spring原生支持的方案。核心是继承AbstractRoutingDataSource,重写determineCurrentLookupKey方法,用ThreadLocal保存当前数据源标识。AOP在方法执行前切换,执行后清理。适合读写分离、多库动态路由。

第三种,用现成轮子:dynamic-datasource-spring-boot-starter。这是目前最推荐的方式。一个注解@DS就能切换,支持分组、负载均衡、事务、健康检查。下面重点讲这个。

快速上手:dynamic-datasource

第一步,引入依赖:

xml
复制
下载
运行
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>4.3.0</version> </dependency>

第二步,application.yml配置:

yaml
复制
下载
spring: datasource: dynamic: primary: master strict: false datasource: master: url: jdbc:mysql://localhost:3306/order_db username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver slave: url: jdbc:mysql://localhost:3307/user_db username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver

primary指定默认数据源,strict设为false表示找不到匹配数据源时回退到主库。

第三步,在Service方法上加@DS:

java
复制
下载
@Service public class OrderService { @Autowired private OrderMapper orderMapper; @DS("master") public void createOrder(Order order) { orderMapper.insert(order); } @DS("slave") public List<Order> queryOrders() { return orderMapper.selectList(null); } }

@DS可以加在方法上,也可以加在类上。方法级优先于类级。不加注解时走primary数据源。

关键坑点,一个都别踩

坑一:@DS和@Transactional同时使用时,数据源切换失效。因为Spring事务在方法执行前就开启了,此时数据源已经绑定。@DS的AOP默认在事务AOP之后执行,导致切换不生效。解决办法:把@DS加在事务方法的外层,或者用@DS配合@Transactional(propagation = Propagation.REQUIRES_NEW),确保切换发生在事务开启前。更稳妥的做法是,把数据源切换逻辑放在Controller层或独立的方法中。

坑二:多数据源下MyBatis-Plus分页插件配置。如果每个数据源有独立的SqlSessionFactory,需要分别配置分页插件。用dynamic-datasource时,它统一管理SqlSessionFactory,只需正常配置MybatisPlusInterceptor即可,不用重复配。

坑三:事务管理器。dynamic-datasource会自动配置DataSourceTransactionManager,但如果手动配置了多个,要确保@Transactional指定正确的transactionManager。否则会出现“事务不生效”或“数据源错乱”。

坑四:连接池监控。多数据源下,Druid或HikariCP的监控页面可能只显示一个数据源。需要为每个数据源单独配置StatFilter和监控Servlet,否则排查连接泄漏时两眼一抹黑。

坑五:循环依赖与懒加载。多个数据源互相引用时,启动可能报循环依赖。加@Lazy注解延迟初始化,或把数据源配置类拆分,避免Bean创建顺序问题。

手动实现方案(备选)

如果不想引入第三方依赖,可以手动实现。核心是:

定义多个DataSource Bean,用@ConfigurationProperties绑定配置。

创建DynamicDataSource继承AbstractRoutingDataSource,把多个数据源放入targetDataSources。

用ThreadLocal保存数据源key,AOP在方法前后设置和清除。

为每个数据源配置独立的SqlSessionFactory和Mapper扫描路径。

代码量大约200行,适合对可控性要求极高的场景。但多数项目,dynamic-datasource已经足够。

总结

多数据源配置不难,难的是事务、切换时机和监控。记住三点:优先用dynamic-datasource,@DS注意和@Transactional的顺序,每个数据源都要配连接池监控。把这篇收藏,下次配多数据源,十分钟搞定。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询