閒談 Transactional註解失效

2021-10-23 18:21:50 字數 1410 閱讀 6378

@transactional 註解能保證方法內多個資料庫操作原子性(要麼同時成功、要麼同時失敗),使用@transactional註解時需要注意使用方法,不然@transactional會失效。

protected、private 修飾的方法上使用 @transactional 註解,雖然事務無效,但不會有任何報錯

之所以會失效是因為在spring aop **時,如上圖所示 transactioninterceptor (事務***)在目標方法執行前後進行攔截,dynamicadvisedinterceptor(cglibaopproxy 的內部類)的 intercept 方法或 jdkdynamicaopproxy 的 invoke 方法會間接呼叫 abstractfallbacktransactionattributesource的 computetransactionattribute 方法,獲取transactional 註解的事務配置資訊。

此方法會檢查目標方法的修飾符是否為 public,不是 public則不會獲取@transactional 的屬性配置資訊。

propagation屬性

propagation 代表事務的傳播行為,預設值為 propagation.required,其他的屬性資訊如下:

其中propagation.supports、propagation.not_supported、propagation.never,事務將不會發生回滾。

rollbackfor 可以指定能夠觸發事務回滾的異常型別。spring預設丟擲了未檢查unchecked異常(繼承自 runtimeexception 的異常)或者 error才回滾事務。

其他異常不會觸發回滾事務。如果在事務中丟擲其他型別的異常,但卻期望 spring 能夠回滾事務,就需要指定rollbackfor屬性。

開發中避免不了會對同乙個類裡面的方法呼叫,比如有乙個類test,它的乙個方法a,a再呼叫本類的方法b(不論方法b是用public還是private修飾),但方法a沒有宣告註解事務,而b方法有。則外部呼叫方法a之後,方法b的事務是不會起作用的。

這種情況是因為使用spring aop**造成的,因為只有當事務方法被當前類以外的**呼叫時,才會由spring生成的**物件來管理。

在業務方法中一般不需要catch異常,如果非要catch一定要丟擲throw new runtimeexception(),或者註解中指定拋異常型別@transactional(rollbackfor=exception.class),否則會導致事務失效,資料commit造成資料不一致,所以有些時候try catch反倒會畫蛇添足。

常用的mysql資料庫預設使用支援事務的innodb引擎。一旦資料庫引擎切換成不支援事務的myisam,那事務就從根本上失效了。

Transactional註解初見

之前一直使用宣告式事務,切面程式設計的配置方式讓程式設計者忘記了事務的存在,一旦離開,發現這個事務還是蠻重要的 public inte ce userservice transactional public class userserviceimpl implements userservice p...

Transactional配置詳解

1 事務的7種屬性 propagation required 支援當前事務,如果當前沒有事務,就新建乙個事務。預設配置,也是常用的選擇。propagation supports 支援當前事務,如果當前沒有事務,就以非事務方式執行。propagation mandatory 支援當前事務,如果當前沒有...

Transactional註解詳解

預設遇到throw new runtimeexception 會回滾 需要捕獲的throw new exception 不會回滾 指定回滾 transactional rollbackfor exception.class public void methodname 指定不回滾 transacti...