日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring Transaction Propagation 事务传播

發布時間:2025/7/14 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring Transaction Propagation 事务传播 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

spring Transaction中有一個很重要的屬性:Propagation。主要用來配置當前需要執行的方法,與當前是否有transaction之間的關系。

我曉得有點兒抽象,這也是為什么我想要寫這篇博客的原因。看了后面的例子,大家應該就明白了。

一、Propagation取值:

REQUIRED(默認值):在有transaction狀態下執行;如當前沒有transaction,則創建新的transaction;

SUPPORTS:如當前有transaction,則在transaction狀態下執行;如果當前沒有transaction,在無transaction狀態下執行;

MANDATORY:必須在有transaction狀態下執行,如果當前沒有transaction,則拋出異常IllegalTransactionStateException;

REQUIRES_NEW:創建新的transaction并執行;如果當前已有transaction,則將當前transaction掛起;

NOT_SUPPORTED:在無transaction狀態下執行;如果當前已有transaction,則將當前transaction掛起;

NEVER:在無transaction狀態下執行;如果當前已有transaction,則拋出異常IllegalTransactionStateException。

二、REQUIRED與REQUIRED_NEW

上面描述的6種propagation屬性配置中,最難以理解,并且容易在transaction設計時出現問題的是REQUIRED和REQURED_NEW這兩者的區別。當程序在某些情況下拋出異常時,如果對于這兩者不夠了解,就可能很難發現而且解決問題。

下面我們給出三個場景進行分析:

場景一:

ServiceA.Java:

public class ServiceA {
@Transactional
public void callB() {
serviceB.doSomething();
}
}

ServiceB.java

public class ServiceB {
@Transactional
public void doSomething() {
throw new RuntimeException("B throw exception");
}
}
這種情況下,我們只需要在調用ServiceA.callB時捕獲ServiceB中拋出的運行時異常,則transaction就會正常的rollback。

場景二

在保持場景一中ServiceB不變,在ServiceA中調用ServiceB的doSomething時去捕獲這個異常,如下:

public class ServiceA {
@Transactional
public void callB() {
try {
serviceB.doSomething();
} catch (RuntimeException e) {
System.err.println(e.getMessage());
}
}
}
這個時候,我們再調用ServiceA的callB。程序會拋出org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only這樣一個異常信息。原因是什么呢?

因為在ServiceA和ServiceB中的@Transactional propagation都采用的默認值:REQUREID。根據我們前面講過的REQUIRED特性,當ServiceA調用ServiceB的時候,他們是處于同一個transaction中。如下圖所示:

當ServiceB中拋出了一個異常以后,ServiceB會把當前的transaction標記為需要rollback。但是ServiceA中捕獲了這個異常,并進行了處理,認為當前transaction應該正常commit。此時就出現了前后不一致,也就是因為這樣,拋出了前面的UnexpectedRollbackException。

場景三

在保持場景二中ServiceA不變,修改ServiceB中方法的propagation配置為REQUIRES_NEW,如下:

public class ServiceB {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomething() {
throw new RuntimeException("B throw exception");
}
}
此時,程序可以正常的退出了,也沒有拋出UnexpectedRollbackException。原因是因為當ServiceA調用ServiceB時,serviceB的doSomething是在一個新的transaction中執行的。如下圖所示:

所以,當doSomething拋出異常以后,僅僅是把新創建的transaction rollback了,而不會影響到ServiceA的transaction。ServiceA就可以正常的進行commit。

當然這里把ServiceA和ServiceB放在兩個獨立的transaction是否成立,還需要再多多考慮你的業務需求。

轉載于:https://www.cnblogs.com/bendantuohai/p/5603356.html

總結

以上是生活随笔為你收集整理的spring Transaction Propagation 事务传播的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。