解決SpringBoot中使用@Transactional註解遇到的問題

使用@Transactional註解遇到的問題

1、不建議在接口上添加@Transactional註解

一般在service類標簽上添加@Transactional即可

2、@Transactional註解

隻能應用到public可見度的方法上。如果應用到protected、private或者package可見度的方法上時,不會報錯,但事務也不會起作用

3、默認情況下

spring會對uncheck異常進行事務回滾的;如果是checked異常則不會回滾,可添加註解 @Transactional(rollbackFor=Exception.class) 是的checked異常回滾。

  • uncheck異常:java裡面將派生於Error或者RuntimeException(比如空指針,1/0)的異常
  • checked異常:其他繼承自java.lang.Exception得異常統稱為Checked Exception,如IOException、TimeoutException等

4、數據庫引擎需要支持事務管理

如果是mysql,註意表要使用事務的引擎,比如innodb,如果是myisam,事務不會起作用的

5、同一類中methodA()方法

沒有@Transactional 註解,在其內部調用有@Transactional 註解的方法,有@Transactional 註解的方法methodB()的事務被忽略,不會開啟新的事務,也不會發生回滾。例如:

@Service
public class TransactionService {
public void methodA(){
    this.methodB();
}
@Transactional
public void methodB(){
}
}

原因:Spring采用動態代理(AOP)實現對bean的管理和切片,它為我們的每個class生成一個代理對象。隻有在代理對象之間進行調用時,可以觸發切面邏輯。在 Spring 的 AOP 代理下,隻有目標方法由外部調用,目標方法才由 Spring 生成的代理對象來管理。

詳解:Spring的事務管理是通過AOP實現的,其AOP的實現對於非final類是通過cglib這種方式,即生成當前類的一個子類作為代理類,然後在調用其下的方法時,會判斷這個方法有沒有@Transactional註解,如果有的話,則會開啟一個新的事務,並通過動態代理實現事務管理(攔截方法調用,執行事務等切面)。

當methodA()中調用methodB()時,並不是使用的代理對象,而是普通的javabean,從而導致this.methodB()時也不是代碼對象,從而導致@Transactional失敗,即發現methodA()上並沒有@Transactional註解,所以整個AOP代理過程(事務管理)不會發生。

解決辦法:

1、把這兩個方法分開到不同的類中;

2、把註解@Transactional加到類名上面去;

3、把註解@Transactional加到methodA()方法上,methodB()不添加註解,在調用methodB()時兩個方法的事務都會生效,因為methodA()默認的事務傳播屬性為PROPAGATION_REQUIRED,此時methodB()會加入到methodA()中

@Service
public class TransactionService {
@Transactional
public void methodA(){
    this.methodB();
}
public void methodB(){
}
}

4、獲取本對象的代理對象,再進行調用。具體操作如:

  • Spring-content.xml上下文中,增加配置:<aop:aspectj-autoproxy expose-proxy=”true”/>
  • 在TransactionService 中,用(transactionService )(AopContext.currentProxy()),獲取到TransactionService 的代理類,再調用事務方法,強行經過代理類,激活事務切面。

springboot 註解transactional失效

1、在方法中捕獲瞭異常

那麼該方法事務不會回滾。本類中A方法(有事務註解)調用其他類中B方法(有事務註解,該類在容器中),B方法中捕獲瞭異常,事務失效不可以回滾,在B方法中的catch裡進行異常拋出則可以正常回滾。

本類中A方法(有事務註解)調用其他類中B方法(有事務註解,該類在容器中),A方法中捕獲瞭異常,spring事務機制檢測到異常,進行回滾。

所以最好在業務層catch中拋出異常讓控制層捕獲。

2、spring中事務是代理模式

在該類中A方法調用本類中B方法,A方法上沒有事務註解,B方法上有事務註解,則B方法中出現異常,B方法事務不會回滾,A方法沒有事務註解也不會回滾。

3、A方法如果有事務註解

調用瞭本類B方法,B方法出現異常也整體可回滾。

4、本類中A方法調用

其他類中B方法(有事務註解,該類在容器中),B方法發生異常,可以回滾。

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: