springboot事務不生效的幾種解決方案
最近在業(yè)務中遇到了很奇怪的場景,在加上 @Transactional注解后,插入2條數(shù)據(jù),如果第二條出異常了,第一條不會回滾,排查了很久,上網(wǎng)也找資料看了很久,問題得以解決,總結了事務不生效的幾點可能的原因:
1.mysql的MyISAM引擎不支持回滾,如果需要自動回滾事務,需要將mysql的引擎設置成InnoDB;
2.在業(yè)務中拋出異常時,本應該被事務管理器捕獲的異常,
被手動catch處理了,或者事務結果未滿足具體業(yè)務需求的,如果需要手動catch異常做業(yè)務處理,需要在catch里手動回滾事務TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(),
或者在catch中主動拋出異常throw new RuntimeException();.
3.默認的spring事務只會捕獲RuntimeException,如果是非運行時異常也需要進行事務回滾的話,可以在@Transactional注解中加上rollbackfor = Exception.class屬性;
項目中沒有配置事務管理器(大坑!我遇到的就是這個),需要在配置類或者配置文件中配置,以本人的配置類為例,因為項目是多數(shù)據(jù)源的,所以要區(qū)別配置不同數(shù)據(jù)源的事務管理器.
數(shù)據(jù)源一:
public DataSource getDataSource() {
return createDataSource();
}
@Bean(name = "detTransactionManager")
public PlatformTransactionManager txManager(@Qualifier("detDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
數(shù)據(jù)源二:
@Bean(name = "shardDataSource")
public DataSource getDataSource() {
return buildDataSource();
}
@Bean(name = "shardTransactionManager")
public PlatformTransactionManager txManager(@Qualifier("shardDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
可以看到,兩個事務管理器配置了不同的beanName,接下來只需要 在需要事務控制的位置加上該事務管理器的name就可以完美解決啦!
@Override
@Transactional(value = "detTransactionManager",rollbackFor = Exception.class)
public int updateOrInsert(BaseRequest<BankTemplateDto> param) {