SpringBoot使用dynamic配置多数据源时使用@Transactional事务在非primary的数据源上遇到的问题
情景
- Springboot项目中使用dynamic配置了多个数据源;
- primary(主要)数据源是oracle;
- 其他数据源有postgres;
- 想要在非primary数据源中使用@Transactional进行事务管理;
- 在这之前没有单独配置Transactional事务的bean。
出现的问题
- 非primary数据源中事务的sql检查报错
原因
使用primary数据源的数据库(oracle)方言去检查非primary数据源的数据库(Postgresql)的sql语句,出现sql语法不兼容的情况;
解决方法:
如果使用了springboot dynamic 多数据源配置时,primary数据源和其他数据原的数据库类型不一致,但是还想要在非primary数据源中使用@Transactional事务
- 使用自定义的transactionManager
@Configuration public class TransactionManagerConfig {@Autowiredprivate DataSource dataSource; // 动态数据源@Bean("db1TransactionManager")public DataSourceTransactionManager jiaoyiTransactionManager() {DynamicRoutingDataSource dynamicDataSource = (DynamicRoutingDataSource) dataSource;DataSource jiaoyiDataSource = dynamicDataSource.getDataSource("db1");return new DataSourceTransactionManager(jiaoyiDataSource);}@Bean("db2TransactionManager")public DataSourceTransactionManager clearingTransactionManager() {DynamicRoutingDataSource dynamicDataSource = (DynamicRoutingDataSource) dataSource;DataSource clearingDataSource = dynamicDataSource.getDataSource("db2");return new DataSourceTransactionManager(clearingDataSource);} }
- 在服务中使用
@Service public class MultiDataSourceService {@Autowiredprivate Db1Mapper db1Mapper;@Autowiredprivate Db2Mapper db2Mapper;// 使用db1数据源的事务@Transactional("db1TransactionManager")public void processJiaoyi() {db1Mapper.insertData();}// 使用db2数据源的事务@Transactional("db2TransactionManager")public void processClearing() {db2Mapper.updateData();} }
注意事项
- 数据源切换与事务顺序:
确保@DS注解与@Transactional在同一方法或调用链中,避免数据源切换与事务管理器不匹配。