一.數據庫引擎不支持事務
spring的事務需要底層數據庫引擎的支持
這里以 MySQL 為例,其 MyISAM 引擎是不支持事務操作的,InnoDB 才是支持事務的引擎,一般要支持事務都會使用 InnoDB。
根據 MySQL 的官方文檔:
從 MySQL 5.5.5 開始的默認存儲引擎是:InnoDB,之前默認的都是:MyISAM,所以這點要值得注意,底層引擎不支持事務再怎么搞都是白搭。
MySQL的幾種引擎可以了解 https://www.cnblogs.com/zluckiy/p/13793799.html
二.在非public修飾的方法使用
以下來自 Spring 官方文檔:
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.
大概意思就是 @Transactional
只能用於 public 的方法上,否則事務不會失效,如果要用在非 public 方法上,可以開啟 AspectJ
代理模式。
代碼中解釋:
@Transactional注解使用的是AOP,在使用動態代理的時候只能針對public
方法進行代理,源碼依據在AbstractFallbackTransactionAttributeSource
類中的computeTransactionAttribute
方法中,如下:
1 protected TransactionAttribute computeTransactionAttribute(Method method, 2 Class<?> targetClass) { 3 // Don't allow no-public methods as required. 4 if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { 5 return null; 6 }
此處如果不是標注在public
修飾的方法上並不會拋出異常,但是會導致事務失效。
三.在try.catch代碼段中,沒有將異常拋出,導致事務無法回滾
1 @Transactional 2 public void method(){ 3 try{//錯誤不會回滾 4 //插入一條數據 5 //更改一條數據 6 }catch(Exception ex){ 7 return; 8 } 9 }
四.拋出的異常類型不對,默認為運行時異常RuntimeException
1 @Transactional 2 public void method(){ 3 try{ 4 //插入一條數據 5 //更改一條數據 6 }catch(Exception ex){ 7 return; 8 } 9 }
這樣事務也是不生效的,因為默認回滾的是:RuntimeException,如果你想觸發其他異常的回滾,需要在注解上配置一下,如:
1 @Transactional(rollbackFor = Exception.class)
五.方法中調用同類的方法
1 public class Test{ 2 public void A(){ 3 //插入一條數據 4 //調用B方法 5 B(); 6 } 7 8 @Transactional 9 public void B(){ 10 //插入數據 11 } 12 }
簡單的說就是一個類中的A方法
(未標注聲明式事務)在內部調用了B方法
(標注了聲明式事務),這樣會導致B方法中的事務失效。
為什么會失效呢?:其實原因很簡單,Spring在掃描Bean的時候會自動為標注了@Transactional
注解的類生成一個代理類(proxy),當有注解的方法被調用的時候,實際上是代理類調用的,代理類在調用之前會開啟事務,執行事務的操作,但是同類中的方法互相調用,相當於this.B()
,此時的B方法並非是代理類調用,而是直接通過原有的Bean直接調用,所以注解會失效。
六.配置錯誤導致事務失效
1.Propagation傳播行為配置錯誤
spring默認的事務傳播屬性是Propagation.REQUIRED
,但是一旦配置了錯誤的傳播屬性,也是會導致事務失效,如下三種配置將會導致事務失效:
Propagation.SUPPORTS
Propagation.NOT_SUPPORTED
Propagation.NEVER
2代碼中我們一般通過spring管理,去實現事務,需要注意代碼塊有沒有被spring進行管理
3數據源沒有配置事務管理器等配置相關的問題導致
參考https://javastack.blog.csdn.net/article/details/103871083
https://blog.csdn.net/qq_34162294/article/details/105803966