1、檢查你的方法是不是public的。@Transactional注解只能應用到public可見度的方法上,如果應用在protected、private或者package可見度的方法上,也不會報錯,不過事務設置不會起作用。
2、檢查你的異常類型是不是unchecked異常。默認情況下,Spring會對unchecked異常進行事務回滾,如果是checked異常則不回滾。如空指針異常、算術異常等,會被回滾;文件讀寫、網絡出問題,spring就沒法回滾了。如果你想check異常也回滾怎么辦,注解上面寫明異常類型即可:
@Transactional(rollbackFor = Exception.class)
類型的還有norollbackFor,自定義不回滾的異常。
3、是否在service中進行了try...catch的操作,由於已經被捕獲異常,故事務也不會回滾。如果非要在service中try...catch異常,又想要事務回滾,可在catch塊中拋出運行時異常:
try{ .... }catch(Exception e){ logger.error("",e); throw new RuntimeException; }
這種方法有個不足之處,就是不能在catch塊中存在return子句,若想捕獲異常時回滾事務,同時返回提示信息,可以使用手動回滾:
try{ ... }catch(Exception e){ logger.error("",e); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return ERROR_MESSAGE; }
PS:另外說明一下,在controller層捕獲了service層的異常,事務還會回滾嗎?答案是會的,只要你service層拋出了異常,並且你加的事務可以處理這個異常,也就是rollbackFor = Exception.class這個符合你拋出的異常,不管外面有沒有捕獲都可以回滾。
4、是否開啟了對注解的解析:
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
5、數據庫引擎要支持事務,如果是mysql,注意表要使用支持事務的引擎,比如innodb,如果是myisam,事務是不起作用的。
6、spring是否掃描到你這個包,如下是掃描到org.test下面的包:
<context:component-scan base-package="org.test" ></context:component-scan>
7、檢查是不是同一個類中的方法調用(如A方法無@Transactional注解,調用了一個有@Transactional注解的方法),這樣事務也是不生效的。原因可參照如下文章:
https://blog.csdn.net/levae1024/article/details/82998386
https://blog.csdn.net/gx_hxl/article/details/80808088
https://blog.csdn.net/m0_38027656/article/details/84190949
參考: