SpringBoot多数据源配置,其实没你想的那么难
很多后端开发一听到“多数据源”就头大觉得要写一堆配置、切面、注解还容易踩坑。其实SpringBoot多数据源的核心就一句话动态路由 多个DataSource Bean。搞懂这个半小时就能跑起来。为什么需要多数据源常见场景有三个读写分离主库写、从库读、分库分表不同业务用不同库、老系统迁移新老数据库并存。不管哪种本质都是让不同的SQL请求落到不同的数据库连接上。SpringBoot默认只配一个DataSource多数据源就是要打破这个默认。核心思路AbstractRoutingDataSourceSpring提供了一个AbstractRoutingDataSource它本身不管理连接而是根据一个determineCurrentLookupKey()方法的返回值从内部维护的targetDataSourcesMap里选一个真正的DataSource。所以我们要做三件事定义多个真实的DataSource比如master、slave。写一个类继承AbstractRoutingDataSource重写determineCurrentLookupKey()从ThreadLocal里取当前数据源标识。写一个AOP切面或注解在方法执行前把数据源标识塞进ThreadLocal执行后清理。实战配置步骤假设我们有两个库主库master和从库slave。首先在application.yml里配两个数据源yaml复制下载spring: datasource: master: jdbc-url: jdbc:mysql://localhost:3306/master_db username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver slave: jdbc-url: jdbc:mysql://localhost:3306/slave_db username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver注意多数据源时要用jdbc-url而不是url否则HikariCP会报错。然后写配置类创建两个DataSource Beanjava复制下载Configuration public class DataSourceConfig { Bean(master) ConfigurationProperties(prefix spring.datasource.master) public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } Bean(slave) ConfigurationProperties(prefix spring.datasource.slave) public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } }接着定义动态数据源类java复制下载public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } }DataSourceContextHolder用ThreadLocal保存当前数据源java复制下载public class DataSourceContextHolder { private static final ThreadLocalString CONTEXT new ThreadLocal(); public static void setDataSource(String dataSource) { CONTEXT.set(dataSource); } public static String getDataSource() { return CONTEXT.get(); } public static void clear() { CONTEXT.remove(); } }再注册动态数据源为Primaryjava复制下载Bean Primary public DataSource dynamicDataSource(Qualifier(master) DataSource master, Qualifier(slave) DataSource slave) { MapObject, Object targetDataSources new HashMap(); targetDataSources.put(master, master); targetDataSources.put(slave, slave); DynamicDataSource dynamicDataSource new DynamicDataSource(); dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.setDefaultTargetDataSource(master); return dynamicDataSource; }最后写一个注解和AOP切面java复制下载Target({ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface DS { String value() default master; }java复制下载Aspect Component public class DsAspect { Around(annotation(ds)) public Object around(ProceedingJoinPoint point, DS ds) throws Throwable { DataSourceContextHolder.setDataSource(ds.value()); try { return point.proceed(); } finally { DataSourceContextHolder.clear(); } } }使用时就很简单java复制下载DS(slave) public ListUser queryUsers() { return userMapper.selectAll(); }几个必须注意的坑第一事务问题。Transactional默认只作用于一个数据源如果方法内切换了数据源事务不会跨库。需要分布式事务时得用Seata或消息表。第二MyBatis集成。如果用了MyBatis要确保SqlSessionFactory用的是动态数据源而不是某个具体数据源。通常把动态数据源设为Primary即可。第三数据源切换失效。AOP切面要在Service层生效如果同类方法自调用切面不生效。另外ThreadLocal要在finally里清理防止线程复用串数据。第四连接池监控。多数据源下每个连接池要单独监控否则一个池满了你都不知道。总结SpringBoot多数据源配置核心就是AbstractRoutingDataSource ThreadLocal AOP。不要被“动态”“路由”这些词吓到代码量其实很少。先跑通主从切换再考虑分库分表、事务一致性。记住多数据源不是目的让正确的SQL去正确的库才是。动手试一次你会发现真的没那么难。

相关新闻

Java面试被问烂的10道题,答错3道直接挂

Java面试被问烂的10道题,答错3道直接挂

Java面试中总有一些题被反复问,候选人觉得“太简单”,面试官却用它快速筛人。原因很现实:这些题看似基础,却能暴露你是否真正理解Java的设计哲学。以下10道被问烂的题,答错3道,基本宣告面试失败。1. String…

2026/10/4 21:11:17 阅读更多 →
云桌面或无联网环境如何离线安装VS Code插件:TaoToken统一Key通道下的vsix手动部署与验证

云桌面或无联网环境如何离线安装VS Code插件:TaoToken统一Key通道下的vsix手动部署与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 21:10:16 阅读更多 →
一文详解Cache Aside(旁路缓存模式)

一文详解Cache Aside(旁路缓存模式)

最经典、最常用的缓存设计模式,业务代码自己维护缓存,缓存组件不感知数据库,缓存和 DB 相互独立,所以叫旁路。适用:Redis MySQL 这类组合,几乎所有业务系统都在用。旁路 缓存不在数据库读写的主链路里面&…

2026/10/4 21:10:16 阅读更多 →

最新新闻

基于CNN与OpenCV SSD的人脸情绪识别系统实战:从毕设压缩包到实时推理

基于CNN与OpenCV SSD的人脸情绪识别系统实战:从毕设压缩包到实时推理

简介:这份资源是面向深度学习入门者、毕业设计与课程设计学生的完整人脸情绪识别项目包,围绕卷积神经网络与实时目标检测两条技术路线展开,解决从人脸定位到表情分类的落地问题。压缩包共11个文件、约11.89MB,包含Python源码、模型…

2026/10/4 21:54:04 阅读更多 →
端侧视觉AI工程实战:浏览器中部署神经网络的四大核心层

端侧视觉AI工程实战:浏览器中部署神经网络的四大核心层

1. 这不是“跑个demo”,而是把AI模型塞进浏览器标签页的硬核工程现场“把神经网络塞进一个浏览器标签页”——这句话听起来像极了程序员圈里那种带点戏谑的夸张修辞。但如果你真去翻过TensorFlow.js的GitHub issue、看过ONNX Runtime Web的性能调优文档、或者亲手在…

2026/10/4 21:54:04 阅读更多 →
DeepAgents+MCP+A2A+Skills:工业级Agent集群落地范式

DeepAgents+MCP+A2A+Skills:工业级Agent集群落地范式

1. 这不是又一个“Agent玩具”:为什么DeepAgentsMCPA2ASkills的组合突然成为工业级Agent集群的分水岭你可能已经看过太多“5分钟用LangChain搭个聊天机器人”的教程,也刷到过无数标着“下一代AI Agent”的宣传页——但它们大多止步于单点Demo&#xff1a…

2026/10/4 21:54:04 阅读更多 →
LeGO-LOAM在KITTI数据集上的完整部署与调优指南

LeGO-LOAM在KITTI数据集上的完整部署与调优指南

1. 项目概述:为什么要在KITTI数据集上跑LeGO-LOAM?LeGO-LOAM,全称Lightweight and Ground-Optimized Lidar Odometry and Mapping,是2018年出自密歇根大学团队的一套经典激光SLAM算法。它不是那种“学术玩具”,而是真正…

2026/10/4 21:54:04 阅读更多 →
Matlab中rms函数详解:从有效值计算到性能评价实战

Matlab中rms函数详解:从有效值计算到性能评价实战

开篇直接说重点:rms(均方根)这个函数,几乎是Matlab里被低估得最厉害的函数之一。很多人第一眼以为它只是个统计工具箱里的边角料,实际在做信号质量评估、振动有效值计算、噪声水平度量、模型误差对比这类“结果性能评价…

2026/10/4 21:54:04 阅读更多 →
YOLO监控场景行人检测实战:数据集训练全流程与避坑指南

YOLO监控场景行人检测实战:数据集训练全流程与避坑指南

简介:面向街道监控场景的行人检测数据集,共包含1200张监控视角抓拍图片,标注类别为person,最大特点是已按YOLO系列要求生成txt标签,可直接用于YOLOv3至YOLOv10等全系列算法训练。资源包内总计2000个文件,由…

2026/10/4 21:53:04 阅读更多 →

日新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →