Transcational註解可能失效的情況總結


參考文章:https://blog.csdn.net/weixin_42719412/article/details/85318391

@Transcational註解使用注意點

Spring提供的事務註解@Transcational在以下情況會不生效或者數據不回滾,使用時需要注意

  1. 函數必須是public的,否則事務不生效

  2. 添加有@Transcational註解的函數不應該在該類的內部調用,因爲Spring AOP機制不會攔截內部函數間的調用,所以會導致事務不生效

  3. 數據庫引擎要支持事務,如果是Mysql,注意表要使用支持事務的引擎,比如innodb,如果是myisam,事務不生效

  4. 因爲Spring的事務功能基於AOP,所以該類必須託管於Spring容器內,且必須與調用者處於同一容器內,否則事務不生效

  5. 需要注意是否打開了使用註解進行事務控制,Spring Boot項目默認打開,非Spring Boot項目需要在配置文件中進行如下配置,否則基於@Transcational註解的事務可能不會生效:

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
    
  6. Spring的事務回滾默認只對unchecked異常回滾,如果出現的異常是checked,則不會回滾,如果希望對所有的異常都進行回滾,可以在@Transcational註解中配置屬性,如下:

    @Transactional(rollbackFor=Exception.class)
    

    類似的還有norollbackFor屬性,用於配置不需要回滾的異常

  7. 異常在catch後必須拋出,否則不會進行回滾

事務傳播模式

在使用事務時,很可能會設計到事務之間的嵌套使用,這是就需要指明事務之間的傳播模式。

Propagation枚舉了多種事務傳播模式,部分列舉如下:

  1. REQUIRED(默認模式):業務方法需要在一個容器裏運行。如果方法運行時,已經處在一個事務中,那麼加入到這個事務,否則自己新建一個新的事務。

  2. NOT_SUPPORTED:聲明方法不需要事務。如果方法沒有關聯到一個事務,容器不會爲他開啓事務,如果方法在一個事務中被調用,該事務會被掛起,調用結束後,原先的事務會恢復執行。

  3. REQUIRESNEW:不管是否存在事務,該方法總彙爲自己發起一個新的事務。如果方法已經運行在一個事務中,則原有事務掛起,新的事務被創建。

  4. MANDATORY:該方法只能在一個已經存在的事務中執行,業務方法不能發起自己的事務。如果在沒有事務的環境下被調用,容器拋出例外。

  5. SUPPORTS:該方法在某個事務範圍內被調用,則方法成爲該事務的一部分。如果方法在該事務範圍外被調用,該方法就在沒有事務的環境下執行。

  6. NEVER:該方法絕對不能在事務範圍內執行。如果在就拋例外。只有該方法沒有關聯到任何事務,才正常執行。

  7. NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效。

通過Spring手動控制事務

當因爲一些限制導致我們不能使用@Transcational來完成事務控制時,我們可以自己通過以下方式來開啓並控制事務

1 獲取事務管理器,這裏因爲是用的JPA,所以獲取的是JpaTransactionManager,根據自己項目實際使用的事務管理器來獲取

@Resource
private JpaTransactionManager transactionManager;

2 手動開啓並控制事務

//手動開啓事務
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus transactionStatus = transactionManager.getTransaction(def);
try{
    ...
    //手動提交事務
    transactionManager.commit(transactionStatus);
}catch(Exception e){
    //手動控制事務回滾
    transactionManager.rollback(transactionStatus);
    log.error("數據操作異常,已進行回滾");
    throw e;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章