Java多数据源事务管理需显式指定PlatformTransactionManager,如@Transactional("masterTxManager");禁用跨数据源本地事务,强一致性须用JTA;可自定义路由管理器结合ThreadLocal动态切换,并确保事务管理器、数据源、模板类三者严格对应。

Java 中多数据源环境下切换事务管理器,核心在于让 Spring 知道当前事务该由哪个 PlatformTransactionManager 管理。不能靠自动代理“猜”,必须显式指定或动态路由。
明确声明事务管理器
最直接的方式是在 @Transactional 注解中通过 value 或 transactionManager 属性指定 Bean 名:
-
@Transactional("masterTxManager")—— 使用名为masterTxManager的事务管理器 -
@Transactional("slaveTxManager")—— 使用名为slaveTxManager的事务管理器 - 确保对应的数据源(
DataSource)和事务管理器(DataSourceTransactionManager)已正确定义并注入 Spring 容器
避免跨数据源的同一事务
Spring 原生不支持跨多个物理数据源的分布式事务(JTA 除外)。若一个方法同时操作 master 和 slave:
- 只标注一个
@Transactional("masterTxManager"):slave 上的操作不会被事务控制,提交/回滚不一致 - 不要试图用两个
@Transactional嵌套——事务注解在同一个类内方法调用不生效(代理未介入) - 如需强一致性,应引入 JTA(如 Atomikos、Narayana),配置
JtaTransactionManager,并使用 XA 数据源
动态切换事务管理器(按规则路由)
若希望根据方法名、参数或上下文自动选事务管理器,可自定义 TransactionManager 实现路由逻辑:
立即学习“Java免费学习笔记(深入)”;
- 继承
AbstractPlatformTransactionManager,重写doGetTransaction和doBegin - 结合
ThreadLocal存储当前目标管理器标识(如 "master" / "slave") - 在 service 方法开头用 AOP 或手动设置:
TransactionContext.setTarget("slave") - 让自定义管理器根据该标识委托给真正的
DataSourceTransactionManager
注意事务传播与数据源绑定一致性
事务传播行为(如 REQUIRES_NEW)会创建新事务,但新事务仍走当前线程绑定的事务管理器。务必确保:
- 数据访问层(如
JdbcTemplate或EntityManager)使用的DataSource与事务管理器管理的DataSource是同一个实例 - 不同数据源的
JdbcTemplate要分别配置,并注入对应名称的 bean,调用时别混用 - 开启
@EnableTransactionManagement,且代理模式为proxyTargetClass = true(尤其使用 CGLIB 时)
不复杂但容易忽略:事务管理器、数据源、模板类三者必须一一对应,且事务注解必须作用在 Spring 代理能拦截到的方法上(通常是非 private、非 final、跨 Bean 调用)。


















