當前位置:首頁 » 操作系統 » spring資料庫事物

spring資料庫事物

發布時間: 2023-07-03 22:07:21

1. 「Spring」事務失效的場景

1.資料庫引擎不支持事務

Spring 事務生效的前提是所連接的資料庫要支持事務,如果底層的資料庫引擎都不支持事務,則Spring的事務肯定會失效。

例如: Mysql 用的不是 InnoDB 引擎,而是用的 MyISAM 存儲引擎。

2.事務方法未被 Spring 容器管理

如果事務方法所在的類沒有載入到 Spring IOC 容器中,也就是說,事務方法所在的類沒有被 Spring 容器管理,則Spring事務會失效。

例如:你的方法所在類沒有加@Component或者@Service註解。

3.方法沒有被 public 修飾

如果事務所在的方法沒有被 public 修飾,此時 Spring 的事務也會失效。

4.同一類中方法之間直接的調用

例如:如果同一個類中有兩個歲畢方法分別為 A 和 B,方法 A 沒有添加事務註解,而方法 B 添加了 @Transactional 事務註解,此時方法 A 直接調用方法 B,則方法 B 的事務會失效。

5.未配置事務管理器

如果在項目中沒有配置 Spring 的事務管理器,即使使用了 Spring 的事務管理功能,Spring 的事務也不會生效。

例如:對於 SpringBoot 項目來說,導入了 mybatis 的 starter 依賴後,SpringBoot 會自動注入DataSourceTransactionManager 事務管理器,這樣我們就可以直接用 @Transactional 註解使用事務了。

6.事枯行務傳播類型不支持事務

如果方法的事務傳播類型為不支持事務沒雀嘩的傳播類型,則該方法的事務在 Spring 中會失效。

例如: A 方法的事務傳播類型為 NOT_SUPPORTED,不支持事務,此時用帶事務的方法 B 去調用 A 方法,則 A 方法的事務失效。

7.進行異常捕捉卻沒有拋出

比如對某一個新增數據代碼段進行 try catch 異常,而 catch 里沒有向外拋出異常,此時 spring 事務無法回滾。

8.錯誤的標注異常類型

如果在 @Transactional 註解中標注的異常類型不是我們拋出的異常類型,則Spring事務的回滾會失效。

例如: Spring 中默認回滾的異常類型為 RuntimeException,如果此時你拋出的異常是 Exception,那麼Spring 事務中無法捕獲到 Exception 異常,則事務回滾會失效。

9.開啟多線程

開啟一個線程去執行資料庫操作,多線程內的方法將不被 spring 事務控制。

例如:一個帶事務的方法 A 中開啟線程去執行同類中的一個 insert 方法,即使這個操作失敗了,也不會回滾 A 中的其他資料庫操作。

注意:如果把 insert 方法提出到一個新的類中,加入事務註解,就能成功的把 insert 方法加入到 spring 事務管理中。但是使用多線程事務的情況下,如果想進行回滾,比較麻煩,因為我們感知不到線程中方法執行的異常。

2. spring事務失效的幾種場景以及原因

spring事務失效場景可能大家在很多文章都看過了,所以今天就水一篇,看大家能不能收獲一些不一樣的東西。直接進入主題

失效原因: spring事務生效的前提是,service必須是一個bean對象
解決方案: 將service注入spring

失效原因: spring默認只會回滾非檢查異常和error異常
解決方案: 配置rollbackFor

失效原因: spring事務只有捕捉到了業務拋出去的異常,才能進行後續的處理,如果業務自己捕獲了異常,則事務無法感知
解決方案:
1、將異常原樣拋出;
2、設置TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

失效原因: spring事務切面的優先順序順序最低,但如果自定義的切面優先順序和他一樣,且自定義的切面沒有正確處理異常,則會同業務自己捕獲異常的那種場景一樣
解決鄭含方案:
1、在切面中將異常原樣拋出;
2、在切面中設置TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

失效原因: spring事務默認生效的方法許可權都必須為public

解決方案:
1、將方法改為public;
2、修改TansactionAttributeSource,將publicMethodsOnly改為false【這個從源碼跟蹤得出結論】
3、開啟 AspectJ 代理模式【從spring文檔得出結論】

具體步驟:

1、在pom引入aspectjrt坐標以及相應插件

2、在啟動類上加上如下配置

註: 如果是在idea上運行,則需做如下配置


4、直接用TransactionTemplate

示例:

失效原因: 子容器掃描范圍過大,將未加事務配置的serivce掃描進來

解決方案:
1、父子容器個掃個的范圍;
2、不用父子容器,所有bean都交給同一容器管理

註: 因為示例是使用springboot,而springboot啟動默認沒有父子容器,只有一個容器,因此就該場景就演示示例了

失效原因: 因為spring事務畝轎是用動態代理實現,因此如果方法使用了final修飾,則代理類無法對目標方法進行重寫,植入事務功能

解決方案:
1、方法不要用final修飾

失效原因: 原因和final一樣

解決方案:
1、方法不要用static修飾

失效原因: 本類方法不經過代理,無法進行增強

解決方案:
1、注入自己來調用;
2、使用@EnableAspectJAutoProxy(exposeProxy = true) + AopContext.currentProxy()

失效原因: 因為spring的事務是通過資料庫連接來實現,而資料庫連接spring是放在threadLocal裡面。同一個事務,只能用同一個資料庫連接。而多線程場景下,拿到的資料庫連接是不一樣的,即是屬於不同事務

失效原因: 使用的傳播特性不支持事迅叢肆務

失效原因: 使用了不支持事務的存儲引擎。比如mysql中的MyISAM

註: 因為springboot,他默認已經開啟事務管理器。org.springframework.boot.autoconfigure.jdbc.。因此示例略過

失效原因: 當代理類的實例化早於AbstractAutoProxyCreator後置處理器,就無法被AbstractAutoProxyCreator後置處理器增強

本文列舉了14種spring事務失效的場景,其實這14種裡面有很多都是歸根結底都是屬於同一類問題引起,比如因為動態代理原因、方法限定符原因、異常類型原因等

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-transaction-invalid-case

熱點內容
安卓版微信收藏在哪裡 發布:2025-03-18 23:09:11 瀏覽:155
h5與資料庫連接 發布:2025-03-18 23:07:40 瀏覽:23
c語言編輯是 發布:2025-03-18 23:06:25 瀏覽:982
gamemaker腳本 發布:2025-03-18 23:01:12 瀏覽:358
怎樣給qq文件加密 發布:2025-03-18 22:59:18 瀏覽:613
為什麼qq密碼對卻登錄上 發布:2025-03-18 22:57:54 瀏覽:90
盤錦電腦伺服器 發布:2025-03-18 22:57:51 瀏覽:676
波蘭達演算法 發布:2025-03-18 22:57:10 瀏覽:328
怎麼連接動車上的wifi密碼多少 發布:2025-03-18 22:49:34 瀏覽:531
密碼放在什麼文件夾裡面 發布:2025-03-18 22:48:12 瀏覽:316