Springboot 事物管理

2021-09-25 16:11:29 字數 3537 閱讀 5407

spring 事務管理分為程式設計式和宣告式的兩種方式。

程式設計式事務指的是通過編碼方式實現事務;宣告式事務基於 aop,將具體業務邏輯與事務處理解耦。宣告式事務管理使業務**邏輯不受汙染, 因此在實際使用中宣告式事務用的比較多。宣告式事務有兩種方式,一種是在配置檔案(xml)中做相關的事務規則宣告,另一種是基於 @transactional 註解的方式。本文將著重介紹基於 @transactional 註解的事務管理。

@transactional 可以作用於介面、介面方法、類以及類方法上。當作用於類上時,該類的所有 public 方法將都具有該型別的事務屬性,同時,我們也可以在方法級別使用該標註來覆蓋類級別的定義。

雖然 @transactional 註解可以作用於介面、介面方法、類以及類方法上,但是 spring 建議不要在介面或者介面方法上使用該註解,因為這只有在使用基於介面的**時它才會生效。另外, @transactional 註解應該只被應用到 public 方法上,這是由 spring aop 的本質決定的。如果你在 protected、private 或者預設可見性的方法上使用 @transactional 註解,這將被忽略,也不會丟擲任何異常。

預設情況下,只有來自外部的方法呼叫才會被aop**捕獲,也就是,類內部方法呼叫本類內部的其他方法並不會引起事務行為,即使被呼叫方法使用@transactional註解進行修飾。

:springboot專案會自動配置乙個 datasourcetransactionmanager,所以我們只需在方法(或者類)加上 @transactional 註解,就自動納入 spring 的事務管理了

如下在方法加上 @transactional 註解,丟擲異常之後,事務會自動回滾,資料不會插入到資料庫。

@transactional

public void insertuser()

spring的事務管理預設是針對***unchecked exception**回滾,也就是預設對error異常和runtimeexception異常以及其子類進行事務回滾,且必須丟擲異常,若使用try-catch對其異常捕獲則不會進行回滾!(error異常和runtimeexception異常丟擲時不需要方法呼叫throws或try-catch語句);而checked exception*** 則必須用try語句塊進行處理或者把異常交給上級方法處理總之就是必須寫**處理它,所以必須在service捕獲異常,然後再次丟擲,這樣事務方才起效。

它們兩個是一樣的意思。當配置了多個事務管理器時,可以使用該屬性指定選擇哪個事務管理器。

事務的傳播行為,預設值為 propagation.required。

可選的值有:

propagation.required

如果當前存在事務,則加入該事務,如果當前不存在事務,則建立乙個新的事務。

如a方法和b方法都新增了註解,使用預設傳播模式,則a方法內部呼叫b方法,會把兩個方法的事務合併為乙個事務。

propagation.supports

如果當前存在事務,則加入該事務;如果當前不存在事務,則以非事務的方式繼續執行。

propagation.mandatory

如果當前存在事務,則加入該事務;如果當前不存在事務,則丟擲異常。

propagation.requires_new

重新建立乙個新的事務,如果當前存在事務,暫停當前的事務。這個屬性可以實現:

類a中的a方法加上預設註解@transactional(propagation = propagation.required),類b中的b方法加上註解@transactional(propagation = propagation.requires_new),然後在a方法中呼叫b方法運算元據庫,再在a方法最後丟擲異常,會發現a方法中的b方法對資料庫的操作沒有回滾,因為propagation.requires_new會暫停a方法的事務。

propagation.not_supported

以非事務的方式執行,如果當前存在事務,暫停當前的事務。

propagation.never

以非事務的方式執行,如果當前存在事務,則丟擲異常。

propagation.nested

和 propagation.required 效果一樣。

事務的隔離級別,預設值為 isolation.default。

可選的值有:

isolation.default

使用底層資料庫預設的隔離級別。

isolation.read_uncommitted

isolation.read_committed

isolation.repeatable_read

isolation.serializable

事務的超時時間,預設值為-1。如果超過該時間限制但事務還沒有完成,則自動回滾事務。

指定事務是否為唯讀事務,預設值為 false;為了忽略那些不需要事務的方法,比如讀取資料,可以設定 read-only 為 true。

用於指定能夠觸發事務回滾的異常型別,可以指定多個異常型別。

丟擲指定的異常型別,不回滾事務,也可以指定多個異常型別。

這裡面有幾點需要大家留意:

a. 乙個功能是否要事務,必須納入設計、編碼考慮。不能僅僅完成了基本功能就ok。

b. 如果加了事務,必須做好開發環境測試(測試環境也盡量觸發異常、測試回滾),確保事務生效。

c. 以下列了事務使用過程的注意事項,請大家留意。

1.不要在介面上宣告@transactional ,而要在具體類的方法上使用 @transactional 註解,否則註解可能無效。

2.不要圖省事,將@transactional放置在類級的宣告中,放在類宣告,會使得所有方法都有事務。故@transactional應該放在方法級別,不需要使用事務的方法,就不要放置事務,比如查詢方法。否則對效能是有影響的。

3.使用了@transactional的方法,對同乙個類裡面的方法呼叫, @transactional無效。比如有乙個類test,它的乙個方法a,a再呼叫test本類的方法b(不管b是否public還是private),但a沒有宣告註解事務,而b有。則外部呼叫a之後,b的事務是不會起作用的。(經常在這裡出錯)

4.使用了@transactional的方法,只能是public,@transactional註解的方法都是被外部其他類呼叫才有效,故只能是public。道理和上面的有關聯。故在 protected、private 或者 package-visible 的方法上使用 @transactional 註解,它也不會報錯,但事務無效。

5.spring的事務在拋異常的時候會回滾,如果是catch捕獲了,事務無效。可以在catch裡面加上throw new runtimeexception();

6.最後有個關鍵的一點:和鎖同時使用需要注意:由於spring事務是通過aop實現的,所以在方法執行之前會有開啟事務,之後會有提交事務邏輯。而synchronized**塊執行是在事務之內執行的,可以推斷在synchronized**塊執行完時,事務還未提交,其他執行緒進入synchronized**塊後,讀取的資料不是最新的。

所以必須使synchronized鎖的範圍大於事務控制的範圍,把synchronized加到controller層或者大於事務邊界的呼叫層!

SpringBoot事物無效

今天發現使用者註冊的service的事務並沒有起到作用,再丟擲乙個runtimeexception後,並沒有發生回滾,下面是除錯步驟 1 檢查資料庫的引擎是否是innodb 2 啟動類上是否加入 enabletransactionmanagement註解 3 是否在方法上加入 transaction...

springboot學習十 事物管理 整合jpa

一,事物管理 只需在方法上加 transactional註解 或在類上加 transactional 二 整合jpa 1,pom org.springframework.boot spring boot starter data jpa spring datasource username root...

spring boot 中事物的使用

事務,通俗的說就是,同時做多個事,要麼全做,要麼不做,也是其特性。舉個例子來說,好比你在某寶 某東 某多上購物,在你提交訂單的時候,庫存也會相應減少,不可能是錢付了,庫存不減少,或者庫存減少了,錢沒扣,不是尷尬了。沒描述清楚?那好,我們結合例項,通過 實現,我想往資料庫加兩個學生,如果增加乙個失敗了...