@Transactional註解失效場景
阿新 • • 發佈:2021-09-13
@Transactional註解可以作用於哪些地方
可作用在類、介面、類方法。
- 作用於類:註解在類上,表示該類所有public方法都配置相同的事務屬性資訊。
- 作用於方法:當類和方法都配置了
@Transactional
,方法的事務會覆蓋類的事務配置資訊。 - 作用於介面:不推薦這種,因為一旦標註在Interface上並且配置了Spring AOP 使用CGLib動態代理,將會導致
@Transactional
註解失效
@Transactional註解有哪些屬性?
propagation屬性
Propagation.REQUIRED
:如果當前存在事務,則加入該事務,如果當前不存在事務,則建立一個新的事務。(Propagation.SUPPORTS
:如果當前存在事務,則加入該事務;如果當前不存在事務,則以非事務的方式繼續執行。Propagation.MANDATORY
:如果當前存在事務,則加入該事務;如果當前不存在事務,則丟擲異常。Propagation.REQUIRES_NEW
:重新建立一個新的事務,如果當前存在事務,暫停當前的事務。( 當類A中的 a 方法用預設Propagation.REQUIRED
模式,類B中的 b方法加上採用Propagation.REQUIRES_NEW
Propagation.REQUIRES_NEW
會暫停 a方法的事務 )Propagation.NOT_SUPPORTED
:以非事務的方式執行,如果當前存在事務,暫停當前的事務。Propagation.NEVER
:以非事務的方式執行,如果當前存在事務,則丟擲異常。Propagation.NESTED
:和 Propagation.REQUIRED 效果一樣。
isolation 屬性
預設隔離級別預設值為 Isolation.DEFAULT
。
- TransactionDefinition.ISOLATION_DEFAULT:
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔離級別,允許讀取尚未提交的資料變更,可能會導致髒讀、幻讀或不可重複讀
- TransactionDefinition.ISOLATION_READ_COMMITTED: 允許讀取併發事務已經提交的資料,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生
- TransactionDefinition.ISOLATION_REPEATABLE_READ: 對同一欄位的多次讀取結果都是一致的,除非資料是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生。
- TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止髒讀、不可重複讀以及幻讀。但是這將嚴重影響程式的效能。通常情況下也不會用到該級別。
timeout 屬性
timeout
:事務的超時時間,預設值為 -1。如果超過該時間限制但事務還沒有完成,則自動回滾事務。
readOnly 屬性
readOnly
:指定事務是否為只讀事務,預設值為 false;為了忽略那些不需要事務的方法,比如讀取資料,可以設定 read-only 為 true。
rollbackFor 屬性
rollbackFor
:用於指定能夠觸發事務回滾的異常型別,可以指定多個異常型別。
noRollbackFor屬性**
noRollbackFor
:丟擲指定的異常型別,不回滾事務,也可以指定多個異常型別。
@Transactional失效場景
-
註解在非public方法上會失效。
因為Spring AOP 代理時,
computeTransactionAttribute
方法會檢查目標方法的修飾符是否為 public,不是 public則不會獲取@Transactional
的屬性配置資訊。 -
propagation註解屬性錯誤。
-
註解屬性 rollbackFor 設定錯誤。
繼承自
RuntimeException
的異常或者Error
及其這兩個的子類才回滾事務,其他異常不觸發回滾。 -
同一個類方法呼叫,導致失效。
同一個類,方法A(沒有宣告註解事物)呼叫方法B(宣告註解事物),方法B事務不起作用。
Spring AOP
代理造成的。 -
異常被catch“吃了”導致失效
很常見,自己又犯過。在後期改造過程中,沒考慮失效場景。
-
資料庫引擎不支援事物