Java中JDBC多数据源切换需借助Spring的AbstractRoutingDataSource实现:配置多个真实数据源、一个继承该类的路由数据源(重写determineCurrentLookupKey)、ThreadLocal上下文持有器;通过自定义注解+AOP自动切换,注意事务方法上使用且需在事务开启前完成切换。

Java 中 JDBC 本身不支持多数据源切换,真正可行的方案是借助 Spring 的 AbstractRoutingDataSource 实现运行时动态路由,让 JDBC 操作(如 JdbcTemplate 或 MyBatis)自动使用对应的数据源。
核心组件必须配齐
要让切换生效,三个角色缺一不可:
-
多个真实数据源:比如
masterDataSource和slaveDataSource,各自独立配置 URL、用户名、驱动、连接池等; -
一个路由数据源:继承
AbstractRoutingDataSource,重写determineCurrentLookupKey()方法,从ThreadLocal中读取当前线程绑定的 key(如"master"); -
上下文持有器:用
ThreadLocal<String>存储当前线程应使用的数据源标识,提供set()、get()、clear()方法,避免线程复用污染。
切换动作靠注解 + AOP 自动完成
手动调 DataSourceContextHolder.set("slave") 会污染业务代码。推荐做法是:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 定义一个自定义注解,例如:
@TargetDataSource("slave"); - 写一个切面,在目标方法执行前调用
setDataSourceType("slave"); - 方法结束后必须调用
clearDataSourceType(),否则后续同一线程可能误用旧 key。
Spring 配置不能漏关键细节
光写代码不够,配置错一步就切换失败:
立即学习“Java免费学习笔记(深入)”;
- 把所有真实数据源放入路由数据源的
targetDataSources映射中,例如:map.put("master", masterDataSource); - 指定默认数据源(
defaultTargetDataSource),并把路由数据源声明为@Primary; -
SqlSessionFactory或JdbcTemplate必须注入这个路由数据源,否则切换无效。
事务场景要特别注意时机
如果方法加了 @Transactional,数据源切换必须在事务开启前完成。因为 Spring 的事务管理器会在事务开始时锁定数据源连接,之后再改 ThreadLocal 也无济于事。所以注解必须加在事务方法上,且不能放在 private 方法或内部调用链中。

















