问题现象
最近接手一个项目,和同事一起做,过程中同事问到代码中的声明式事物@Transactional
注解怎么不起作用,抛出了异常但是事物并没有回滚
问题原因
起初怀疑是不是出现以下用法问题:
- 声明式事物是基于动态代理实现,如果出现在类内部this调用则会绕过动态代理,导致事物失效
@Transactional
默认情况下,只会在以下两个异常出现时才会回滚
By default, a transaction will be rolling back on {@link RuntimeException} and {@link Error}
但是根据排查都不属于以上两种情况,但是我发现当前这个项目用的是多数据源,会不会是这个原因,翻看了一下数据源事物自动装配类的源码:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(DataSource.class)
static class DataSourceTransactionManagerConfiguration {
@Bean
@ConditionalOnMissingBean(PlatformTransactionManager.class)
DataSourceTransactionManager transactionManager(DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
return transactionManager;
}
}
}
其中@ConditionalOnSingleCandidate(DataSource.class)
这行代码代表只有在单数据源的情况下才会自动装配事务管理器,所以确实是因为多数据源导致的。
解决方案
一般如果用到多数据源的话,可能需要涉及分布式事务管理,但是我们这里业务比较简单不需要分布式事务,只需要在一个库上能实现事务就可以了,我们用的多数据源组件是这个dynamic-datasource,自然也是先翻看官方文档:https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611,比较尴尬的是文档付费观看
所以还是看看源码,DynamicDataSourceAutoConfiguration
类中有这么一段:
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
@ConditionalOnProperty(prefix = DynamicDataSourceProperties.PREFIX, name = "seata", havingValue = "false", matchIfMissing = true)
public Advisor dynamicTransactionAdvisor() {
DynamicLocalTransactionInterceptor interceptor = new DynamicLocalTransactionInterceptor();
return new DynamicDataSourceAnnotationAdvisor(interceptor, DSTransactional.class);
}
当分布式事务seata未配置或者配置false的时候,会装配本地事务拦截的这个切面,拦截@DSTransactional
注解的方法,这就明白了,本地事务应该是需要换成这个注解,经测试确实有效。
评论区