問題描述:最近發現一個加了@Transactional註解的事務沒有生效
問題分析:
一、註解特性
1、service類標籤(一般不建議在接口上)上添加@Transactional,可以將整個類納入spring事務管理,在每個業務方法執行時都會開啓一個事務,不過這些事務採用相同的管理方式。
2、@Transactional 註解只能應用到 public 可見度的方法上。 如果應用在protected、private或者 package可見度的方法上,也不會報錯,不過事務設置不會起作用。
3、默認情況下,Spring會對unchecked異常進行事務回滾;如果是checked異常則不回滾。
辣麼什麼是checked異常,什麼是unchecked異常
java裏面將派生於Error或者RuntimeException(比如空指針,1/0)的異常稱爲unchecked異常,其他繼承自java.lang.Exception得異常統稱爲Checked Exception,如IOException、TimeoutException等
辣麼再通俗一點:你寫代碼出現的空指針等異常,會被回滾,文件讀寫,網絡出問題,spring就沒法回滾了。然後我教大家怎麼記這個,因爲很多同學容易弄混,你寫代碼的時候有些IOException我們的編譯器是能夠檢測到的,說以叫checked異常,你寫代碼的時候空指針等死檢測不到的,所以叫unchecked異常。這樣是不是好記一些啦
4、只讀事務:
@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
只讀標誌只在事務啓動時應用,否則即使配置也會被忽略。
啓動事務會增加線程開銷,數據庫因共享讀取而鎖定(具體跟數據庫類型和事務隔離級別有關)。通常情況下,僅是讀取數據時,不必設置只讀事務而增加額外的系統開銷。
二、事務傳播行爲
傳播行爲 | 意義 |
---|---|
PROPAGATION_MANDATORY | 表示該方法必須運行在一個事務中。如果當前沒有事務正在發生,將拋出一個異常 |
PROPAGATION_NESTED | 表示如果當前正有一個事務在進行中,則該方法應當運行在一個嵌套式事務中。被嵌套的事務可以獨立於封裝事務進行提交或回滾。如果封裝事務不存在,行爲就像PROPAGATION_REQUIRES一樣。 |
PROPAGATION_NEVER | 表示當前的方法不應該在一個事務中運行。如果一個事務正在進行,則會拋出一個異常。 |
PROPAGATION_NOT_SUPPORTED | 表示該方法不應該在一個事務中運行。如果一個現有事務正在進行中,它將在該方法的運行期間被掛起。 |
PROPAGATION_SUPPORTS | 表示當前方法不需要事務性上下文,但是如果有一個事務已經在運行的話,它也可以在這個事務裏運行。 |
PROPAGATION_REQUIRES_NEW | 表示當前方法必須在它自己的事務裏運行。一個新的事務將被啓動,而且如果有一個現有事務在運行的話,則將在這個方法運行期間被掛起。 |
PROPAGATION_REQUIRES | 表示當前方法必須在一個事務中運行。如果一個現有事務正在進行中,該方法將在那個事務中運行,否則就要開始一個新事務。 |
三、事務隔離級別
在一個典型的應用程序中,多個事務同時運行,經常會爲了完成他們的工作而操作同一個數據。併發雖然是必需的,但是會導致一下問題:
- 髒讀(Dirty read)-- 髒讀發生在一個事務讀取了被另一個事務改寫但尚未提交的數據時。如果這些改變在稍後被回滾了,那麼第一個事務讀取的數據就會是無效的。
- 不可重複讀(Nonrepeatable read)-- 不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但每次查詢結果都不相同時。這通常是由於另一個併發事務在兩次查詢之間更新了數據。
- 幻影讀(Phantom reads)-- 幻影讀和不可重複讀相似。當一個事務(T1)讀取幾行記錄後,另一個併發事務(T2)插入了一些記錄時,幻影讀就發生了。在後來的查詢中,第一個事務(T1)就會發現一些原來沒有的額外記錄。
隔離級別 | 含義 |
---|---|
ISOLATION_DEFAULT | 使用後端數據庫默認的隔離級別。 |
ISOLATION_READ_UNCOMMITTED | 允許讀取尚未提交的更改。可能導致髒讀、幻影讀或不可重複讀。 |
ISOLATION_READ_COMMITTED | 允許從已經提交的併發事務讀取。可防止髒讀,但幻影讀和不可重複讀仍可能會發生。 |
ISOLATION_REPEATABLE_READ | 對相同字段的多次讀取的結果是一致的,除非數據被當前事務本身改變。可防止髒讀和不可重複讀,但幻影讀仍可能發生。 |
ISOLATION_SERIALIZABLE | 完全服從ACID的隔離級別,確保不發生髒讀、不可重複讀和幻影讀。這在所有隔離級別中也是最慢的,因爲它通常是通過完全鎖定當前事務所涉及的數據表來完成的。 |
四、檢查範圍
1、檢查你方法是不是public的
2、你的異常類型是不是unchecked異常
如果我想check異常也想回滾怎麼辦,註解上面寫明異常類型即可
1 |
|
類似的還有norollbackFor,自定義不回滾的異常
3、數據庫引擎要支持事務,如果是MySQL,注意表要使用支持事務的引擎,比如innodb,如果是myisam,事務是不起作用的
4、是否開啓了對註解的解析
1 |
|
5、spring是否掃描到你這個包,如下是掃描到org.test下面的包
1 |
|
6、檢查是不是同一個類中的方法調用(如a方法調用同一個類中的b方法)
7、異常是不是被你catch住了