Spring 事務失敗的八大常見場景,注意避免陷阱

Mondo 文化 更新 2024-01-29

@service public class service1 }
原因:Spring 預設只回滾非檢查異常。

解決方案:配置 rollbackfor 屬性。

* `transactional(rollbackfor = exception.class)`
choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql
@service public class service2 }catch (filenotfoundexception e)
原因:只有當目標自行處理異常時,事務通知才能回滾,如果目標自行處理異常,則無法知道事務通知。

解決方案 1:按原樣丟擲異常。

* 將拋出新的執行時異常(e)新增到catch塊中`
解決方案 2:手動設定 TransactionStatussetrollbackonly()

* 新增 transactioninterceptor. 到 catch 塊currenttransactionstatus().setrollbackonly();
choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql
@service public class service3 }
choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@aspect public class myaspect ", pjp.gettarget())try catch (throwable e)
原因:事務切片的優先順序最低,但如果自定義切片的優先順序與他的相同,則自定義切片仍在內層,如果自定義切片沒有正確丟擲異常...

解決方案:與案例 2 中的解決方案相同。

解決方案 3:調整切片的順序並將它們新增到 myaspect 上@order(ordered.lowest_precedence - 1)(不推薦)。

choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@service public class service4 }
原因:Spring 為該方法建立了 **,新增了事務通知,並假定該方法是公共的。

解決方案 1:更改為 public 方法。

解決方案 2:按如下方式新增 Bean 配置(不推薦)。

choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@bean public transactionattributesource transactionattributesource()
choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

package day04.tx.app.service; // ..service public class service5 }
Controller 類。 choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

package day04.tx.app.controller; // ..controller public class accountcontroller }
應用配置類。

choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@configuration @componentscan("day04.tx.app.service") @enabletransactionmanagement // ..public class appconfig
Web 配置類。

choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@configuration @componentscan("day04.tx.app") // ..public class webconfig
現在配置了父子容器,webconfig 對應子容器,appconfig 對應父容器,發現事務仍然無效。

原因:子容器掃瞄範圍過大,掃瞄沒有事務配置的服務。

解決方案1:掃瞄每乙個,不要讓它變得簡單。

解決方案 2:不要使用父子容器,將所有 Bean 放在同乙個容器中。

choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@service public class service6 @transactional(propagation = propagation.requires_new, rollbackfor = exception.class) public void bar() throws filenotfoundexception }
原因:此類方法不是通過**呼叫的,因此無法增強。

解決方案 1:依賴項注入本身 (**)

解決方案 2:通過 aopcontext 獲取 ** 物件並呼叫它。

方案三:通過CTW和LTW實現功能增強。

解決方案1選擇這裡 j**ascripttypescripthtmlcssshellpythongolangj**acc++c phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@service public class service6 @transactional(propagation = propagation.requires_new, rollbackfor = exception.class) public void bar() throws filenotfoundexception }
解決方案 2,您還需要將其新增到 appconfig 中@enableaspectjautoproxy(exposeproxy = true)

choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@service public class service6 @transactional(propagation = propagation.requires_new, rollbackfor = exception.class) public void bar() throws filenotfoundexception }
choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@service public class service7 ", frombalance); if (frombalance - amount >= 0) public int findbalance(int accountno)
上面的**其實是有bug的,假設from餘額是1000,兩個執行緒都來轉1000,可能會有負扣。

原因:事務的原子性只涵蓋插入、更新、刪除、選擇等對於 UPDATE 語句,SELECT 方法不會阻塞。

如上圖所示,紅線和藍線查詢都發生在扣款之前,並且都認為他們有足夠的餘額進行扣款。

針對上述問題,我們可以在方法中新增同步鎖來解決嗎?

choose here j**ascripttypescripthtmlcssshellpythongolangj**acc++c#phprubyswiftkotlinscalarustdartelixirhaskellluaperlrsql

@service public class service7 ", frombalance); if (frombalance - amount >= 0) public int findbalance(int accountno)
答案是否定的,原因如下:

synchronized 只保證了 target 方法的原子性,commit 等操作被包圍在 target 方法周圍,不在 sync 塊中。

從下圖可以看出,只要在紅線提交之前執行了藍線的查詢,那麼它仍然會查詢到有足夠的餘額1000來轉賬。

解決方案 1:應將同步範圍擴充套件到 ** 方法呼叫。

解決方案 2:使用 select...。for update 而不是 select

相關問題答案

    道醫八界

    道教醫學有八個境界,即 醫道 醫德 醫術 醫學科學 醫學智慧 醫學思維 醫學 醫術。.醫學道教任何想成為大夫的人,一定都熟悉 蘇溫 甲 乙 黃帝針經 明堂六經 三部九候 五臟六臟 麵內穴 中藥對 張仲京 王書和 阮河南 範東陽 張淼 金少等經典。還要了解陰陽生平,萬家規律,五萬億燒龜和 周易 六,必...

    哲學家的八個特徵

    哲學家是一群追求真理和智慧的人,他們以深入思考和提出哲學問題為己任。作為哲學家,他們擁有一些獨特的特徵和品質,使他們不僅是哲學家,而且是他們智慧和人生成就的重要因素。本文將哲學家的八大特徵,希望能給讀者帶來思考和啟迪的食糧。一批判性思維 哲學家具有高度的批判性思維能力。他們不會盲目地追隨或接受所有的...

    了解翡翠的八大領域

    翡翠的八大領域是了解翡翠的重要知識點,不同領域的翡翠在品質 特性 品質上都不同。下面我們將詳細介紹硬玉的八大領域及其特點。.莫西沙場。磨溪沙廠口是著名的琉璃翡翠田之一,其翡翠原石以透明度高 基底乾淨 質地緊緻著稱。磨溪沙廠口的翡翠原石以灰白色為主,綠色較少,但一旦出現綠色,色澤鮮豔飽和,收藏價值高。...

    保持警惕!假女友的八個特徵

    閨蜜是女人一生中最親密的伴侶之一,她們分享彼此的喜怒哀樂,一起經歷人生的起起落落。然而,有時我們可能會遇到假女友,他們表面上與我們親密,但在幕後他們卻有不良動機。為了保護自己,我們需要警惕這些假女友,以下是假女友的八個特徵。只有當你成功時,它才會出現。假女朋友通常只在你取得一些成功或成就時才會出現,...

    10月必吃的八種蔬菜

    棕白 結構 為水生蔬菜,軟硬適中,肉質細嫩,汁液豐富。生長環境 它生長在水生環境中。生理特性 含糖量高,味甜,富含水分 脂肪和蛋白質,營養價值高。用途 可生吃或油炸食用。常見的烹飪方法有油燉和炒肉。文化 是月必吃的蔬菜之一,廣受歡迎。但是,它含有較多的草酸,與鈣結合會形成結石,因此不宜多吃。 蓮藕 ...