1. 程式人生 > 其它 >@Transactional註解失效場景

@Transactional註解失效場景

@Transactional註解可以作用於哪些地方

可作用在類、介面、類方法。

  • 作用於類:註解在類上,表示該類所有public方法都配置相同的事務屬性資訊。
  • 作用於方法:當類和方法都配置了@Transactional,方法的事務會覆蓋類的事務配置資訊。
  • 作用於介面:不推薦這種,因為一旦標註在Interface上並且配置了Spring AOP 使用CGLib動態代理,將會導致@Transactional註解失效

@Transactional註解有哪些屬性?

propagation屬性
  • Propagation.REQUIRED:如果當前存在事務,則加入該事務,如果當前不存在事務,則建立一個新的事務。(
    也就是說如果A方法和B方法都添加了註解,在預設傳播模式下,A方法內部呼叫B方法,會把兩個方法的事務合併為一個事務
  • Propagation.SUPPORTS:如果當前存在事務,則加入該事務;如果當前不存在事務,則以非事務的方式繼續執行。
  • Propagation.MANDATORY:如果當前存在事務,則加入該事務;如果當前不存在事務,則丟擲異常。
  • Propagation.REQUIRES_NEW:重新建立一個新的事務,如果當前存在事務,暫停當前的事務。( 當類A中的 a 方法用預設Propagation.REQUIRED模式,類B中的 b方法加上採用 Propagation.REQUIRES_NEW
    模式,然後在 a 方法中呼叫 b方法操作資料庫,然而 a方法丟擲異常後,b方法並沒有進行回滾,因為Propagation.REQUIRES_NEW會暫停 a方法的事務 )
  • Propagation.NOT_SUPPORTED:以非事務的方式執行,如果當前存在事務,暫停當前的事務。
  • Propagation.NEVER:以非事務的方式執行,如果當前存在事務,則丟擲異常。
  • Propagation.NESTED :和 Propagation.REQUIRED 效果一樣。
isolation 屬性

預設隔離級別預設值為 Isolation.DEFAULT

  • TransactionDefinition.ISOLATION_DEFAULT:
    使用後端資料庫預設的隔離級別,Mysql 預設採用的 REPEATABLE_READ隔離級別 Oracle 預設採用的 READ_COMMITTED隔離級別.
  • 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失效場景

  1. 註解在非public方法上會失效。

    因為Spring AOP 代理時,computeTransactionAttribute 方法會檢查目標方法的修飾符是否為 public,不是 public則不會獲取@Transactional 的屬性配置資訊。

  2. propagation註解屬性錯誤。

  3. 註解屬性 rollbackFor 設定錯誤。

    繼承自 RuntimeException 的異常或者 Error及其這兩個的子類才回滾事務,其他異常不觸發回滾。

  4. 同一個類方法呼叫,導致失效。

    同一個類,方法A(沒有宣告註解事物)呼叫方法B(宣告註解事物),方法B事務不起作用。Spring AOP代理造成的。

  5. 異常被catch“吃了”導致失效

    很常見,自己又犯過。在後期改造過程中,沒考慮失效場景。

  6. 資料庫引擎不支援事物