Spring的@Transactional註解的失效場景?

背景
  1. @Transactional放在類上面和放在方法上面的優先級。註解放在方法上面會覆蓋放在類上面。

  2. @Transactional註解的屬性的含義:事務傳播?事務隔離級別?是否只讀?

  3. 失效的場景有哪些?

    a) 內部方法調用

    b) try…catch

    c) 默認是RuntimeException級別的,那麼Exception級別的異常框架就感知不到

過程
  • 內部方法調用

    場景描述:一個方法沒有事務,但是調用了一個有事務的方法,此事務失效。

    測試代碼

    1. 設計兩個方法。methodA(), methodB()
    2. methodA是沒有事務註解的。
    3. methodB是有事務註解的。
    4. 測試methodA去調用methodB。
    5. 此時methodB方法中,先執行更新數據庫,然後出現異常,未捕獲。

    測試結果

    事務失效。數據被更新到數據庫中。

    雖然代碼報錯了,但是數據庫的更新操作,依然發生了。

    本意是要保證事務,當代碼拋出異常了,那麼事務就回滾了。但是,由於方法間的調用關係,導致了事務失效。

  • try…catch

    方法中出現了異常,且未捕獲。Spring的默認異常感知級別是RuntimeException,因此如果是Exception級別的異常,Spring是無法感知的。此時如果數據已經更新到數據庫了,發生了Exception級別的異常,則不會回滾。事務失效

    如果出現了異常,但是捕獲了。數據庫中的數據最終會被更新。事務失效

  • 默認是RuntimeException級別的,那麼Exception級別的異常框架就感知不到

  1. 在測試try catch的時候,如果捕獲了異常,則數據最終被更新到數據庫中。事務失效,因爲捕獲了異常,並處理了異常。
  2. 如果沒有捕獲異常,則框架感知到異常發生的級別是RuntimeException,如果代碼拋出了Exception級別的異常,則事務依然失效。
小結
  1. 遇到異常檢測不回滾

    原因:默認RuntimeException級別纔回滾。如果是Exception級別的異常需要手動添加@Transactional(rollbackFor=Exeception.class)。

  2. 主動捕獲異常導致框架無法捕獲,從而導致事務失效

  3. 一個合理實踐是這樣的

    a, 業務service層,直接拋出異常,讓Controller層捕獲異常並處理。

    b,這樣實踐後,當service層發生了異常情況。而業務層的異常被框架感知到了,因此事務是有效的。這裏的框架就是Spring的事務。

    c, 注意:非常重要。一定要注意級別:rollbackFor=Exeception.class

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