@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 appconfigWeb 配置類。
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