Transactional的失效場景

2021-10-04 16:05:26 字數 2755 閱讀 1310

@transactional我們在日常開發中經常用到,可能會經常遇到@transactional失效的情況。下面將從what、where、when三個方面講解@transactional。

事務(transaction)是指我們做的一系列完整的事情,在事務中,任何一步出現了問題,這件事情就未算完成。這裡的事務是指對資料庫的增刪改操作,事務的操作具有以下特性:

原子性:事務是個完整的個體,事務內的操作要麼全部成功,要麼全部失敗。

一致性:事務中的操作結果要保證資料達到預期的結果。

隔離性:乙個事務的操作對另乙個事務時不可見的。

永續性:事務的操作結果要儲存在資料庫中,具有永續性。

是指在**中實現事務的開啟、提交或回滾等操作,**的侵入性較強。程式設計式事務可以在**中精確的定位事務的邊界。對於程式設計式事務管理,spring推薦使用transactiontemplate。

try

catch

(exception e)

宣告式事務是建立在aop之上的。本質就是使用動態**對方法的前後進行攔截,實現事務的提交或者回滾。宣告式事務的最大優點就是不需要通過程式設計對事務進行管理。這樣就不需要在業務**中參雜複雜的事務管理的**。我們只需要通過在配置檔案中配置需要新增事務的方法(或者使用@transactional註解)就能進行事務管理。宣告式事務也有兩種實現方式,一是基於tx和aop的xml配置檔案方式,二種就是基於@transactional註解了。

@transactional

public string user()

@transactional可以用在介面、類和方法上。

propagation屬性

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

isolation 屬性

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

timeout屬性

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

readonly 屬性

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

rollbackfor 屬性

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

norollbackfor屬性

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

@transactional 應用在非 public 修飾的方法上

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

protected transactionattribute computetransactionattribute

(methodmethod,

class<

?> targetclass)

顯然非public方法會返回null。

資料庫引擎不支援事務

資料庫引擎要支援事務,如果是mysql,注意表要使用支援事務的引擎,比如innodb,如果是myisam,事務是不起作用的。

事務的propagation屬性配置錯誤

配置了propagation.not_supported或transactiondefinition.propagation_never屬性

rollbackfor 設定錯誤,@transactional 註解失效

spring預設丟擲了未檢查unchecked異常(繼承自 runtimeexception 的異常)或者 error才回滾事務;其他異常不會觸發回滾事務。如果在事務中丟擲其他型別的異常,但卻期望 spring 能夠回滾事務,就需要指定 rollbackfor屬性。

方法之間的互相呼叫也會導致@transactional失效

例如:乙個操作使用者的userservice類中有兩個public方法a和b,a方法呼叫b方法,a上沒有@transactional,而b上有。當controller層呼叫a方法時,b方法上的事務將不會生效。

原因是由於spring的aop導致的,因為只有當事務方法被當前類以外的**呼叫時,才會由spring生成的**物件來管理。

異常被你的 catch「吃了」導致@transactional失效

這種情況是最常見的一種@transactional註解失效場景:

@transactional

private integer a

() throws exception

catch

(exception e)

return insert;

}

如果a方法內部拋了異常,而a方法此時try catch了b方法的異常,那這個事務就不能正常回滾,而是會報出異常。

解決方法:

第一宣告事務的時候加上rollback=『exception』

第二 cath**塊裡面手動回滾

以上就是@transactional的失效場景。

Transactional 失效的場景

1.非public方法上使用會失效 2.開發中避免不了會對同乙個類裡面的方法呼叫,比如有乙個類test,它的乙個方法a,a再呼叫本類的方法b 不論方法b是用public還是private修飾 但方法a沒有宣告註解事務,而b方法有。則外部呼叫方法a之後,方法b的事務是不會起作用的。這也是經常犯錯誤的乙...

Transactional註解初見

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

Transactional配置詳解

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