Spring宣告式事務@Transactional使用
背景
作為一個後端開發,@Transactional一直在用,但總會碰到各種離奇的不生效的情況,每次都是到處查資料解決。就想寫一篇文章整理一下,後面遇到就不用到處找了,有新情況也再補充。
@Transactional
宣告式事務
spring支援 程式設計式事務 和 宣告式事務 兩種。程式設計式事務也就是用程式碼手動控制事務的開始、提交或回滾,這樣業務程式碼就變得不純粹,功能程式碼和輔助程式碼雜糅到一起,並且會有許多重複程式碼。所以我們一般使用宣告式事務。宣告式事務一般有兩種方式,一是基於tx和aop名稱空間的xml配置檔案,二是使用@Transactional註解。目前使用比較廣泛的就是@Transactional註解。
屬性
屬性 | 型別 | 描述 |
---|---|---|
value、transactionManager | String | 可選的限定描述符,指定使用的事務管理器 |
propagation | enum: Propagation | 可選的事務傳播行為設定 |
isolation | enum: Isolation | 可選的事務隔離級別設定 |
readOnly | boolean | “讀寫”或“只讀”事務,預設false讀寫 |
timeout | int (in seconds granularity) | 事務超時時間設定,預設-1 |
rollbackFor | Class物件陣列,必須繼承自Throwable | 導致事務回滾的異常類陣列 |
rollbackForClassName | 類名陣列,必須繼承自Throwable | 導致事務回滾的異常類名字陣列 |
noRollbackFor | Class物件陣列,必須繼承自Throwable | 不會導致事務回滾的異常類陣列 |
noRollbackForClassName | 類名陣列,必須繼承自Throwable | 不會導致事務回滾的異常類名字陣列 |
value、transactionManager
指定事務管理器的名稱,一般用在多資料來源應用的事務處理中,用來明確指定使用哪個資料來源的事務管理
propagation:事務傳播行為【todo 後面寫demo程式碼跑一下驗證】
- Propagation.REQUIRED
- 如果當前存在事務,則加入該事務;如果當前沒有事務,則建立一個新的事務。這是預設值。
- 【外層事務和內層事務是一個事務,要提交一起提交,要回滾一起回滾】
- Propagation.SUPPORTS
- 如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續執行。
- 【如果有外層事務,那麼和Propagation.REQUIRED相同。如果沒有外層事務,以非事務的方式執行】
- Propagation.MANDATORY
- 如果當前存在事務,則加入該事務;如果當前沒有事務,則丟擲異常。
- 【如果有外層事務,那麼和Propagation.REQUIRED相同。如果沒有外層事務,丟擲異常】
- Propagation.REQUIRES_NEW
- 建立一個新的事務,如果當前存在事務,則把當前事務掛起。
- 【外層事務回滾,內部事務正常提交;內部事務回滾,外部事務若對異常進行了捕獲,沒有再向上拋,則外部事務繼續執行】
- Propagation.NOT_SUPPORTED
- 以非事務方式執行,如果當前存在事務,則把當前事務掛起。
- 【外層事務不影響,內層以非事務方式執行】
- Propagation.NEVER
- 以非事務方式執行,如果當前存在事務,則丟擲異常。
- Propagation.NESTED
- 如果當前存在事務,則建立一個事務作為當前事務的巢狀事務來執行;如果當前沒有事務,則該取值等價於Propagation.REQUIRED。
- 【外部事務回滾,內部事務一定會回滾;內部事務回滾,外部事務繼續執行】
Propagation.REQUIRES_NEW、Propagation.NESTED、Propagation.REQUIRED 對比 定義serviceA.methodA()以Propagation.REQUIRED修飾; | |||
異常狀態 | Propagation.REQUIRES_NEW (兩個獨立事務) | Propagation.NESTED (B的事務巢狀在A的事務中) | Propagation.REQUIRED (同一個事務) |
methodA拋異常 methodB正常 | A回滾,B正常提交 | A與B一起回滾 | A與B一起回滾 |
methodA正常 methodB拋異常 | 1.如果A中捕獲B的異常,並沒有繼續向上拋異常,則B先回滾,A再正常提交; 2.如果A未捕獲B的異常,預設則會將B的異常向上拋,則B先回滾,A再回滾 | B先回滾,A再正常提交 | A與B一起回滾 |
methodA拋異常 methodB拋異常 | B先回滾,A再回滾 | A與B一起回滾 | A與B一起回滾 |
methodA正常 methodB正常 | B先提交,A再提交 | A與B一起提交 | A與B一起提交 |
isolation:事務隔離級別
和資料庫的事務隔離級別含義是相同的,只是多了default。區別是isolation指定的是當前連線會話的事務隔離級別,而資料庫指的是當前資料庫全域性的事務隔離級別。當二者不相同時,以當前會話的隔離級別為準。
- Isolation.DEFAULT
- 使用資料庫預設的事務隔離級別
- Isolation.READ_UNCOMMITTED
- 讀未提交
- Isolation.READ_COMMITTED
- 讀已提交
- Isolation.REPEATABLE_READ
- 可重複讀
- Isolation.SERIALIZABLE
- 序列化
readOnly
- 設定當前事務是否為只讀事務,設定為true表示只讀,false則表示可讀寫,預設值為false
- 如果設定為true卻執行了寫的操作會發生什麼呢?後面寫demo跑一下
timeout
- 設定事務的超時秒數,預設值為-1表示永不超時。超時事務將會回滾。
rollbackFor
- 該屬性用於設定需要進行回滾的異常類陣列,當方法中丟擲指定異常陣列中的異常時,則進行事務回滾。例如:
- 指定單一異常類:@Transactional(rollbackFor=RuntimeException.class)
- 指定多個異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
rollbackForClassName
- 該屬性用於設定需要進行回滾的異常類名稱陣列,當方法中丟擲指定異常名稱陣列中的異常時,則進行事務回滾。
- 指定單一異常類名稱:@Transactional(rollbackForClassName="RuntimeException")
- 指定多個異常類名稱:@Transactional(rollbackForClassName={"RuntimeException","Exception"})
noRollbackFor
-
該屬性用於設定不需要進行回滾的異常類陣列,當方法中丟擲指定異常陣列中的異常時,不進行事務回滾。
-
指定單一異常類:@Transactional(noRollbackFor=RuntimeException.class)
-
指定多個異常類:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
noRollbackForClassName
- 該屬性用於設定不需要進行回滾的異常類名稱陣列,當方法中丟擲指定異常名稱陣列中的異常時,不進行事務回滾。
- 指定單一異常類名稱:@Transactional(noRollbackForClassName="RuntimeException")
- 指定多個異常類名稱:@Transactional(noRollbackForClassName={"RuntimeException","Exception"})
使用
- @Transactional要修飾在介面實現類或介面實現方法上,而不是介面類中
- 方法上註解屬性會覆蓋類註解上的相同屬性
- 父類的宣告的@Transactional會對子類的所有方法進行事務增強;子類覆蓋重寫父類方式可覆蓋其@Transactional中的宣告配置
- 只有來自外部的方法呼叫才會被AOP代理捕獲,也就是,類內部方法呼叫本類內部的其他方法並不會引起事務行為,即使被呼叫方法使用@Transactional註解進行修飾
- @Transactional修飾 public 的方法才起作用
- 介面中異常(執行時異常)被捕獲而沒有被丟擲,將不會進行事務回滾
原理
【todo 我不配,用好了再學習一下】
參考
透徹的掌握 Spring 中 @transactional 的使用
Spring中的@Transactional(rollbackFor = Exception.class)屬性詳解
相關文章
- Spring @Transactional 宣告式事務揭祕Spring
- spring事物配置,宣告式事務管理和基於@Transactional註解的使用Spring
- Spring事務的介紹,以及基於註解@Transactional的宣告式事務Spring
- Spring中@Transactional事務使用陷阱Spring
- 三 Spring 宣告式事務Spring
- Spring-宣告式事務Spring
- Spring宣告式事務控制Spring
- spring宣告式事務管理配置Spring
- Spring的事務管理(二)宣告式事務管理Spring
- 深刻理解Spring宣告式事務Spring
- 五(二)、spring 宣告式事務xml配置SpringXML
- JavaEE(12)Spring整合Mybaits、宣告式事務JavaSpringAI
- Springboot資料庫事務處理——Spring宣告式事務Spring Boot資料庫
- Spring宣告式事務控制原理之宣告式事務的重要元件在AOP中的應用Spring元件
- Spring宣告式事務純xml模式回顧SpringXML模式
- Spring筆記(4) - Spring的程式設計式事務和宣告式事務詳解Spring筆記程式設計
- 【Spring註解】事務註解@TransactionalSpring
- 筆記53-Spring jdbcTemplate&宣告式事務筆記SpringJDBC
- Spring宣告式事務的兩種實現方式Spring
- Spring程式設計式和宣告式事務例項講解Spring程式設計
- Spring非同步Async和事務Transactional註解Spring非同步
- 為什麼有人不推薦使用spring官方推薦的@Transactional宣告式註解Spring
- day15-宣告式事務
- 《四 spring原始碼》spring的事務註解@Transactional 原理分析Spring原始碼
- Spring中使用@Async與@Transactional協調非同步與事務處理Spring非同步
- Spring官方都推薦使用的@Transactional事務,為啥我不建議使用!Spring
- 保護億萬資料安全,Spring有“宣告式事務”絕招Spring
- day16-宣告式事務-02
- springboot專案-宣告式事務失效Spring Boot
- Java開啟事務(@Transactional)Java
- Spring Cloud Feign 宣告式服務呼叫SpringCloud
- 宣告式服務呼叫 Spring Cloud FeignSpringCloud
- 使用Spring Boot實現分散式事務Spring Boot分散式
- Spring Data JPA系列4——Spring宣告式數事務處理與多資料來源支援Spring
- 分散式事務之Spring事務與JMS事務(二)分散式Spring
- 11.日誌和事務@Transactional
- Spring Cloud Alibaba 使用Seata解決分散式事務SpringCloud分散式
- 使用Spring實現反應式事務(Reactive Transactions)SpringReact