關於springboot項目使用@Transactional註解事務不回滾的問題

數據庫的事務在我們的項目中應用廣泛,最近在一個springboot項目中遇到了使用@Transactional註解後事務不回滾的問題,代碼如下:

後來查資料發現是因爲數據庫(MySQL)用的引擎是MyISAM,而MySQL的MyISAM引擎不支持回滾事務,如果需要自動回滾事務,需要將MySQL的引擎設置成InnoDB,並不是因爲代碼的問題造成的事務不回滾

在此總結造成事務不回滾可能的原因:

1、首先要看數據庫本身對應的庫、表所設置的引擎是什麼;MyIsam不支持事務,如果需要,則必須改爲InnnoDB

2、@Transactional所註解的方法是否爲public;如果應用在protected、private的方法上,也不會報錯,不過事務設置不會起作用

3、@Transactional所註解的方法所在的類,是否已經被註解@Service或@Component等標記

4、需要調用該方法且需要支持事務特性的調用方是在有@Transactional註解所在的類的外面;注意:類內部的其他方法調用這個註解了@Transactional的方法,事務是不會起作用的

注:service類標籤(一般不建議在接口上)上添加@Transactional,可以將整個類納入spring事務管理,在每個業務方法執行時都會開啓一個事務,不過這些事務採用相同的管理方式

5、@Transactional註解的位置:@Transactional註解必須和拋出異常的位置在一起;在Service中加入的事務註解,手動拋出異常時要在Service中拋出,才能看到效果;如果Controller中,調用兩個不同Service的方法並開啓了事務回滾,要想事務生效,則需要在Controller也加入@Transactional註解

6、在業務中拋出異常時,本應該被事務管理器捕獲的異常被手動catch處理了,或者事務結果未滿足具體業務需求的,如果需要手動catch異常做業務處理,需要在catch裏手動回滾事務:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

或者在catch中主動拋出異常:

throw new RuntimeException();

7、註解爲事務範圍的方法中,事務的回滾僅僅對於unchecked的異常有效,對於checked異常無效,也就是說事務回滾僅僅發生在出現RuntimeException或Error的時候

注:什麼是checked異常,什麼是unchecked異常?

java裏面將派生於Error或者RuntimeException(比如空指針、4/0)的異常稱爲unchecked異常,其他繼承自java.lang.Exception得異常統稱爲Checked Exception,如IOException、TimeoutException等

通俗點就是代碼中出現的空指針等異常會被回滾,而文件讀寫、網絡出問題,spring就沒法回滾了

如果checked異常也需要進行事務回滾的話,可以在@Transactional註解中加上rollbackFor=Exception.class屬性,如下:

@Transactional(rollbackFor=Exception.class)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章