在業務的開發中難免會使用到事務。
事務的ACID
- A(Atomicity) 原子性 :一個事務的最終狀態只能是執行完成或未執行,不存在執行一半行爲的情況。
- C(Consistency) 一致性:事務在執行的前後,從一個狀態變成另一個狀態,總體的數據保持完整性。
- I(Isolation) 隔離性:一個事務執行過程中對另一個事務沒有影響,相互獨立。並且一個事務在執行是看待另一個事務只能是執行完成或未執行的狀態。
- D(Durability) 持久性:一個事務在執行結束後數據的改變是永久的。
在Spring中使用了註解的形式對事務提供了良好的支持和方便的使用。下面是具體的介紹和使用方法。
源碼切入
從源碼可以看出:
- 註解主要作用於類和方法 當類和方法都標註時,會優先按方法的配置。
- 如果沒有聲明任何回滾異常,默認遇到RuntimeException觸發回滾, 也就是遇到其他Exception時無法回滾。
- 當你使用try catch捕捉異常後,異常將無法被回滾。
參數分析
value / transactionManager
用來標註事務管理器bean名稱org.springframework.transaction.PlatformTransactionManager
propagation
配置事務的傳播行爲。具體有7種存在如下枚舉類中:
類型 | 說明 | 適用場景 |
---|---|---|
REQUIRED | 默認類型 當前如果存在事務就加入,若沒有新建一個事務 | 一般情況下 |
SUPPORTS | 當前如果存在事務就加入,不存在則以非事務形式運行 | 適合事務可以有可無的情況 |
MANDATORY | 當前如果存在事務就加入,不存在則拋出異常 | 適合必須要在前一個事務中執行的情況 |
REQUIRES_NEW | 新建事務,如果當前存在事務則把當前事務暫停(suspending) | 適合單獨需要新建事務的情況 |
NOT_SUPPORTED | 非事務的形式運行,如果當前存在事務把當前事務暫停(suspending) | 適合不需要被事務影響的情況 |
NEVER | 以非事務的形式執行,如果當前存在事務則拋出異常) | 適合必須不在事務中運行,獲取異常處理的情況 |
NESTED | 如果當前事務存在,則在嵌套事務內運行 | 這個沒怎麼明白 |
Isolation
/**
* Use the default isolation level of the underlying datastore.
* All other levels correspond to the JDBC isolation levels.
* @see java.sql.Connection
*/
事務的隔離級別 默認使用的是數據庫底層隔離級別。 MySQL的innodb引擎默認支持的是 REPEATABLE-READ(可重複讀)
-
Isolation.READ_UNCOMMITTED讀取未提交數據(會出現髒讀, 一個事務會讀取到另一個事務未提交的數據)基本不使用
-
Isolation.READ_COMMITTED讀取已提交數據(會出現不可重複讀和幻讀)
-
Isolation.REPEATABLE_READ可重複讀(會出現幻讀)
-
Isolation.SERIALIZABLE串行化 最高的級別,確保了事務之間不會產生錯誤,但性能相對較低。
timeout
事務的超時時間 默認也是使用數據庫系統的內置超時時間,超過這個時間事務自動回滾。MySQL中默認超時時間爲50s,可以自行設置。
readOnly
只讀屬性,默認爲false。當設置爲true時 事務爲只讀事務,相當於數據庫是隻讀的。用於一個事務的多條查詢之間保持數據的正確性,防止在事務操作的過程中,數據被另一個完成的事務修改導致了兩次的不一致性。
如圖所示 事務1 兩次查詢,如果要保持一致性,那麼事務2的修改數據操作就不能發生。
rollbackFor
需要回滾的異常類型,默認爲Java中受檢查的異常。
包括RuntimeException 及其子類 和 Error 。
由於業務中常常直接拋出Exception 通常可設置成
@Transactional(rollbackFor = Exception.class)
也可以實現繼承RuntimeException的自定義異常,然後
@Transactional(rollbackFor = MyRuntimeException.class)
rollbackForClassName
聲明需要回滾的異常類名,String類型,可以不定義也可以定義一個數組
noRollbackFor noRollbackForClassName
不需要回滾的異常類和類名,和上述兩個參數使用方法不盡相同。
使用方法
直接在Service層的方法或者類上註釋即可。Spring會採用AOP的形式進行事務的實現。
總結
通過這次學習,我們知道了@Transactional註解爲我們帶來了很多方便,可以對事務進行簡單的處理。但是也需要注意可能帶來的風險,比如回滾失敗的多種情況,可能沒有聲明回滾類,或者事務傳播行爲的錯誤設定。對各個參數的含義都要有深刻的理解,例如各個隔離級別可能造成的錯誤和性能的影響等。
每一次的學習總結,都是一次進步!