1. 工程环境
SpringBoot: 2.2.6.RELEASE
Mybatis-plus: 3.3.0
2. 发现问题
@Transactional(rollbackFor = Exception.class)
public Boolean saveTemplate(VoucherTemplateEntity voucherTemplateEntity, List<VoucherGroupEntity> groupEntityList,
List<VoucherTargetEntity> targetEntityList, List<VoucherCriterionEntity> criterionEntityList,
List<VoucherRuleEntity> ruleEntityList, List<VoucherRightEntity> rightEntityList, List<VoucherNoticeEntity> noticeList) {
//保存分组
if(CollectionUtils.isNotEmpty(groupEntityList)){
voucherGroupMapper.batchInsert(groupEntityList);
}
//保存目标人群
if(CollectionUtils.isNotEmpty(targetEntityList)){
voucherTargetMapper.batchInsert(targetEntityList);
}
//保存生效规则
if(CollectionUtils.isNotEmpty(criterionEntityList)){
voucherCriterionMapper.batchInsert(criterionEntityList);
}
//保存使用规则
if(CollectionUtils.isNotEmpty(ruleEntityList)){
voucherRuleMapper.batchInsert(ruleEntityList);
}
//保存权益
if(CollectionUtils.isNotEmpty(rightEntityList)){
voucherRightMapper.batchInsert(rightEntityList);
}
if(CollectionUtils.isNotEmpty(noticeList)){
voucherNoticeMapper.batchInsert(noticeList);
}
//保存模板
voucherTemplateMapper.insert(voucherTemplateEntity);
throw new NullPointerException();
// return true;
}
很普通的事务使用方式,但是发生异常就是不会回滚,百思不得其解。
3. debug过程
加了各种配置:
spring:
transaction:
rollback-on-commit-failure: true
@EnableTransactionManagement
统统没用
----------------------分割线--------------------
参考了这篇文章
在这个地方发现了问题!!
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
拿到的TransactionManager居然是KafkaTransactionManager !!! WTF??!
![](https://img.haomeiwen.com/i12249756/6429ebcf136e3cf5.png)
点进去查看具体的获取tm方法:
![](https://img.haomeiwen.com/i12249756/3e6222c7ceac83f8.png)
也就是当前的对象是kafka的事务管理器,DataSourceTransactionManager去哪里了,没有注入?
一顿分析,查看相关的配置类:
![](https://img.haomeiwen.com/i12249756/5cca0f365bd8c2e6.png)
这个地方有个@ConditionalOnMissingBean(PlatformTransactionManager.class)
而KafkaTransactionManager恰好是PlatformTransactionManager子类
![](https://img.haomeiwen.com/i12249756/1568f017071fb464.png)
所以默认的TransactionManager就用了KafkaTransactionManager,WTF?这是不是属于Spring的bug
知道了问题就好解决了,百度一下解决方式...
4. 解决方法
参考这个:https://blog.csdn.net/feg545/article/details/113742434
1.要解决DataSourceTransactionManagerAutoConfiguration默认不注册transactionManager的问题
2.让transactionManager变成默认的事务管理器,免得在所有@Transactional指明事务管理器名称
3.要增加一个chainedTransactionManager使得kafka和数据库操作同时在事务中
@Configuration
public class TransactionConfig {
private final DataSource dataSource;
private final TransactionManagerCustomizers transactionManagerCustomizers;
TransactionConfig(DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
this.dataSource = dataSource;
this.transactionManagerCustomizers = transactionManagerCustomizers.getIfAvailable();
}
@Bean //去掉了ConditionalOnMissingBean解决问题1
@Primary //解决问题2
public DataSourceTransactionManager transactionManager(DataSourceProperties properties) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
}
@Bean //解决问题3
public ChainedKafkaTransactionManager chainedKafkaTransactionManager(DataSourceTransactionManager transactionManager,
KafkaTransactionManager<?, ?> kafkaTransactionManager){
return new ChainedKafkaTransactionManager<>(transactionManager, kafkaTransactionManager);
}
}
最后在启动类加上@Transactional(transactionManager = "chainedKafkaTransactionManager")
PROBLEM SOLVED!
网友评论