Spring中 Transactional失效問題

2022-04-16 02:32:22 字數 2257 閱讀 8814

spring中的宣告式註解@transactional很大程度的方便了開發者進行db資料儲存。但是在一些特殊情況下,可能會造成註解不是按想定的方式生效,這裡說幾種可能造成的幾種情況。

這是一種比較簡單不過稍不注意也可能會犯的情況。

spring中事務提交還是回滾是根據呼叫的方法是否丟擲異常來決定的,因此如果把異常捕獲之後又不丟擲的話,即使出了問題,事務還是會提交。

@autowired

private classb b;

@autowired

private classc c;

@transactional

public void methoda() catch (exception e)

}

上例中,想要的結果是b.methodb()c.methodc()同時提交或回滾,但是由於異常**獲,即使在執行方法c的時候出現了異常,方法b的操作仍舊會生效。

(如果方法a是一次轉賬,方法b是轉賬中的加錢操作,方法c是減錢操作,b和c只執行其中乙個的話會導致總金額就發生了變化)

這種也是有可能犯的一種情況。

@transactional只能用於 public 的方法上,否則事務不會失效,如果要用在非 public 方法上,可以開啟aspectj**模式。(預設**模式cglib)

cglib是使用繼承進行動態**的,所以理論上protect方法無修飾符時應該也可以?沒有測試,有空試一下。

這是一種非常容易犯,又不容易察覺的情況。

@component

public class a

@transactional

public void methodb()

}

上例中,methodb的事務是不生效的,因為這裡是同乙個類中的呼叫(更確切的說是同乙個類同乙個物件中),spring事務的原理是呼叫時檢查@transactional註解,然後生成**類進行事務管理,但是內部呼叫時不會生成**類(或者說預設不會),因此也就無法進行事務管理。

這種情況有好幾種解決方法,下面會說到。

非常見是指對@transactional進行了一些屬性的配置導致不生效。

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

// 希望自定義的異常進行回滾

@transactional(propagation= propagation.required,rollbackfor= myexception.class)

這種失效是由於配置錯誤,若是錯誤的配置以下三種 propagation,事務將不會發生回滾。

propagation預設值propagation.required:沒有事務時建立事務。有事務了則加入該事務(相當於使用乙個session)

這是一種最簡單的方法,也就是把上面例子中的methodb拆分到乙個單獨的類裡面,這樣就是一般情況下的事務呼叫。

下面三種方法都是在methodb上新增@transactional(propagation = propagation.requires_new)之後進行的測試

這樣的話就可以在呼叫的時候獲取到**類,並進行方法呼叫:

((testclassa)aopcontext.currentproxy()).insertb();

@component

public class testclassa

用這種方法也可以使methodb的事務生效,但是需要注意的是,第一次生成的**類和自動注入的**類不是乙個物件,也就是**中thistestclassa不是同乙個物件,並且testclassa中不會再次自動注入。

所以如果methodb插入資料時需要當前物件的屬性,這種方法便不能再使用

總之,同類事務不生效是一種很容易疏忽的情況,具體怎麼處理,還是要結合業務。

Spring複習筆記 Spring中的Bean

注意構造器例項化 最常用 靜態工廠方式例項化 例項工廠方式例項化 singleton 單例 始終使用的同乙個物件 預設 prototype 原型 每次都是乙個新的bean例項 request session globalsession websocket init method屬性 用於指定bean...

Spring中 Transactional的使用

1.在需要事務管理的地方加 transactional註解,transactional 註解可以被應用於介面定義和介面方法 類定義和類的 public 方法上.2.transactional 註解只能應用到 public 可見度的方法上,如果你在 protected private 或者 packa...

Spring中classpath中萬用字元號的使用

說明 無萬用字元,必須完全匹配 classpath user base beans.xml 說明 匹配零個或多個字串 只針對名稱,不匹配目錄分隔符等 例如 user a base beans.xml user b base beans.xml 但是不匹配 user base beans.xml cl...