Spring Boot多数据源报错‘no transaction is in progress’排查
问题原因分析
你遇到的TransactionRequiredException本质是多数据源事务管理不匹配导致的:
- 你的
@Transactional注解默认绑定了主数据源的realTransactionManager(因为它被标记为@Primary),但hist数据源的EntityManager属于独立的persistenceUnit,主事务管理器无法管控它的事务上下文。 - 调用
SomeRepositoryHist.save()时,由于没有对应的事务支撑,JPA仅将实体加入持久化上下文,不会立即执行插入SQL,所以看似“只查不插”;而saveAndFlush()强制立即执行数据库操作,此时因无事务直接抛出异常。
解决办法
第一步:完善hist数据源的事务管理器配置
在HistDatasourceConfig的事务管理器Bean上添加明确名称,方便后续引用:
@Bean(name = "histTransactionManager") // 新增name属性 public JpaTransactionManager histTransactionManager(EntityManagerFactory histEntityManager) { return new JpaTransactionManager(histEntityManager); }
第二步:选择事务管理方案
根据业务需求选择以下两种方案之一:
方案1:独立管理两个数据源的事务(无需强一致性)
通过TransactionTemplate分别控制两个数据源的事务,适合不需要两个操作同时成功/失败的场景:
@Service @RequiredArgsConstructor public class SomeService { private final SomeRepository someRepository; private final SomeRepositoryHist someRepositoryHist; // 注入主数据源的事务模板(默认优先注入@Primary的事务管理器) private final TransactionTemplate transactionTemplate; // 注入hist数据源的事务模板 private final @Qualifier("histTransactionManager") TransactionTemplate histTransactionTemplate; @Override public void someMethod() { // 主数据源操作在主事务中执行 transactionTemplate.execute(status -> { SomeEntity entity = new SomeEntity("abc", 123); someRepository.save(entity); return null; }); // hist数据源操作在独立事务中执行 histTransactionTemplate.execute(status -> { SomeEntityHist entityHist = new SomeEntityHist(1L, "abc", 123); someRepositoryHist.save(entityHist); return null; }); } }
方案2:跨数据源事务(保证强一致性)
如果需要两个操作要么都成功、要么都失败,使用ChainedTransactionManager将两个事务管理器链式整合:
- 新增链式事务管理器配置类:
@Configuration public class MultiTransactionConfig { private final JpaTransactionManager realTransactionManager; private final JpaTransactionManager histTransactionManager; public MultiTransactionConfig(@Qualifier("transactionManager") JpaTransactionManager realTransactionManager, @Qualifier("histTransactionManager") JpaTransactionManager histTransactionManager) { this.realTransactionManager = realTransactionManager; this.histTransactionManager = histTransactionManager; } @Bean(name = "chainedTransactionManager") public ChainedTransactionManager chainedTransactionManager() { return new ChainedTransactionManager(realTransactionManager, histTransactionManager); } }
- 修改服务方法的
@Transactional注解,指定使用链式事务管理器:
@Override @Transactional(value = "chainedTransactionManager") public void someMethod() { SomeEntity entity = new SomeEntity("abc", 123); someRepository.save(entity); SomeEntityHist entityHist = new SomeEntityHist(1L, "abc", 123); someRepositoryHist.save(entityHist); }
额外检查项
确认两个@EnableJpaRepositories的basePackages配置正确:
SomeRepository必须位于com.some.project.files.repository.real包下SomeRepositoryHist必须位于com.some.project.files.repository.hist包下
确保各自Repository绑定到对应的EntityManagerFactory。
内容的提问来源于stack exchange,提问作者InspectorGadget
相关产品推荐
相关产品推荐

