Spring詳細(xì)講解7種事務(wù)傳播方式
Spring事務(wù)傳播行為體現(xiàn)在某個(gè)service方法調(diào)用另一個(gè)service方法,事務(wù)該如何進(jìn)行下去。
Spring支持7中事務(wù)傳播方式,在Propagation類中可以看到,如下:
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
使用方式就是在service方法上加入Transational注解,例如:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
下面逐個(gè)介紹下這7中事務(wù)傳播方式:
1. REQUIRED:
Spring的默認(rèn)事務(wù)傳播方式。從字面意思看,它表示此枚舉修飾的service方法必須運(yùn)行在一個(gè)事務(wù)中,如果當(dāng)前存在一個(gè)事務(wù)(比如其他有事務(wù)的service方法調(diào)用此方法),則運(yùn)行在當(dāng)前事務(wù)中,否則開(kāi)啟一個(gè)新的事務(wù)。
示例代碼如下:
注意:這里methodA調(diào)用methodB必須要用Spring的代理方式,即用testService.methodB()方式調(diào)用,如果只是method()方式調(diào)用則相當(dāng)于this.methodB()在本對(duì)象中調(diào)用,事務(wù)不起作用的,一定要是Spring的AOP代理。@Lazy注解是為了防止啟動(dòng)的時(shí)候出現(xiàn)循環(huán)依賴報(bào)錯(cuò),采用懶加載方式注入Bean。
下面示例中,methodA調(diào)用methodB的時(shí)候,會(huì)先開(kāi)啟一個(gè)事務(wù),methodB中會(huì)使用methodA這個(gè)事務(wù),和methodA一起提交或回滾。
@Service public class TestServiceImpl implements TestService { @Resource @Lazy private TestService testService; @Transactional @Override public void methodA() { testService.methodB(); System.out.println("CRUD operation in methodA..."); } @Transactional @Override public void methodB() { System.out.println("CRUD operation in methodB..."); } }
2. SUPPORTS:
從字面意思看,它是支持的意思,也就是有事務(wù)我也支持,沒(méi)有也行。
即:調(diào)用此方法時(shí)如果有一個(gè)事務(wù),那么就在當(dāng)前事務(wù)中執(zhí)行,和當(dāng)前事務(wù)一起提交或回滾。如果當(dāng)前沒(méi)有事務(wù),那么就不開(kāi)啟事務(wù),在無(wú)事務(wù)環(huán)境中執(zhí)行。
下面示例代碼中,methodB是SUPPORTS事務(wù)傳播方式,methodB有沒(méi)有事務(wù)取決于調(diào)用它的methodA??梢钥吹酱藭r(shí)methodA是有一個(gè)事務(wù)的,所以methodB會(huì)在methodA這個(gè)事務(wù)中一起提交或回滾。
@Service public class TestServiceImpl implements TestService { @Resource @Lazy private TestService testService; @Transactional @Override public void methodA() { testService.methodB(); System.out.println("CRUD operation in methodA..."); } @Transactional(propagation = Propagation.SUPPORTS) @Override public void methodB() { System.out.println("CRUD operation in methodB..."); } }
3. MANDATORY:
字面意思:強(qiáng)制。
沒(méi)錯(cuò),就是一定要在事務(wù)中執(zhí)行,否則就會(huì)拋異常。
如下面的代碼,如果直接調(diào)用methodB,由于當(dāng)前沒(méi)有事務(wù),會(huì)拋出一個(gè)IllegalTransactionStateException異常。如果是在methodA中調(diào)用methodB,由于methodA開(kāi)啟了一個(gè)事務(wù),所以methodB會(huì)在methodA的事務(wù)中執(zhí)行,不會(huì)報(bào)錯(cuò)。
@Service public class TestServiceImpl implements TestService { @Resource @Lazy private TestService testService; @Transactional @Override public void methodA() { testService.methodB(); System.out.println("CRUD operation in methodA..."); } @Transactional(propagation = Propagation.MANDATORY) @Override public void methodB() { System.out.println("CRUD operation in methodB..."); } }
4. REQUIRES_NEW:
字面意思:開(kāi)啟一個(gè)新的事務(wù)。
這個(gè)事務(wù)傳播方式會(huì)掛起當(dāng)前事務(wù),開(kāi)啟一個(gè)新的事務(wù),方法會(huì)在新的事務(wù)中執(zhí)行并提交,提交完之后,掛起的事務(wù)繼續(xù)往下走。
如下代碼,methodA調(diào)用methodB的時(shí)候,當(dāng)前事務(wù)會(huì)被掛起,然后在methodB中會(huì)開(kāi)啟一個(gè)新的事務(wù),methodB執(zhí)行完并且事務(wù)提交后,methodA的事務(wù)繼續(xù)執(zhí)行。methodB回滾不影響methodA,methodA回滾也不影響methodB。
@Transactional @Override public void methodA() { testService.methodB(); System.out.println("CRUD operation in methodA..."); } @Transactional(propagation = Propagation.REQUIRES_NEW) @Override public void methodB() { System.out.println("CRUD operation in methodB..."); }
5. NOT_SUPPORTED:
字面意思:不支持事務(wù)。
用該枚舉修飾的方法一定會(huì)運(yùn)行在非事務(wù)環(huán)境中,即使調(diào)用此方法時(shí)有一個(gè)事務(wù),也會(huì)將該事務(wù)掛起。我們通常將這種方式應(yīng)用于強(qiáng)制要求非事務(wù)的方法中,例如我們現(xiàn)在要將批量數(shù)據(jù)去集成第三方接口然后更新?tīng)顟B(tài)到DB,不能說(shuō)某一個(gè)數(shù)據(jù)出錯(cuò)就導(dǎo)致所有數(shù)據(jù)狀態(tài)都回滾,那樣的話,已經(jīng)成功集成過(guò)第三方接口的數(shù)據(jù)就又得重新去集成了,會(huì)造成重復(fù)調(diào)用,導(dǎo)致第三方系統(tǒng)中的數(shù)據(jù)混亂。
如下代碼,methodA有一個(gè)事務(wù),當(dāng)它調(diào)用methodB時(shí),事務(wù)會(huì)被掛起,然后methodB中的CRUD操作不會(huì)在事務(wù)中執(zhí)行,會(huì)立即提交到數(shù)據(jù)庫(kù)。methodB執(zhí)行完之后,methodA的事務(wù)繼續(xù)進(jìn)行,methodA的回滾不影響methodB。
@Transactional @Override public void methodA() { testService.methodB(); System.out.println("CRUD operation in methodA..."); } @Transactional(propagation = Propagation.NOT_SUPPORTED) @Override public void methodB() { System.out.println("CRUD operation in methodB..."); }
6. NEVER:
字面意思:永遠(yuǎn)也不在事務(wù)中運(yùn)行。
該枚舉修飾的方法一旦在事務(wù)環(huán)境中就會(huì)拋異常。
7. NESTED:
字面意思:嵌套事務(wù)。
這種傳播方式稍微有點(diǎn)復(fù)雜,目前各種廠商對(duì)它的支持可能存在差異,需要看具體的事務(wù)管理實(shí)現(xiàn)方式。
用此枚舉修飾的方法,當(dāng)外部有事務(wù)的時(shí)候,會(huì)在里面嵌套一個(gè)事務(wù),里面的事務(wù)回滾不會(huì)影響外部事務(wù),但外部事務(wù)出錯(cuò)回滾會(huì)將里面的也一起回滾。
如下methodB會(huì)在methodA的事務(wù)里面再嵌套一個(gè)事務(wù),當(dāng)methodA事務(wù)提交,methodB也會(huì)跟著一起提交,當(dāng)methodA出錯(cuò)回滾,會(huì)把methodB也一起回滾。當(dāng)methodB出錯(cuò)回滾,不會(huì)影響methodA的事務(wù),事務(wù)會(huì)回退到調(diào)用methodB前的節(jié)點(diǎn),然后繼續(xù)處理后續(xù)的步驟。
@Transactional @Override public void methodA() { System.out.println("CRUD operation in methodA before..."); //保存當(dāng)前狀態(tài),開(kāi)啟嵌套事務(wù) try { testService.methodB(); } catch (Exception e) { e.printStackTrace(); } //methodB回滾后不影響methodA事務(wù)繼續(xù)進(jìn)行 System.out.println("CRUD operation in methodA..."); } @Transactional(propagation = Propagation.NESTED) @Override public void methodB() { System.out.println("CRUD operation in methodB..."); throw new RuntimeException("methodB rollback"); }
到此這篇關(guān)于Spring詳細(xì)講解7種事務(wù)傳播方式的文章就介紹到這了,更多相關(guān)Spring事務(wù)傳播內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot集成itext實(shí)現(xiàn)html轉(zhuǎn)PDF
iText是著名的開(kāi)放源碼的站點(diǎn)sourceforge一個(gè)項(xiàng)目,是用于生成PDF文檔的一個(gè)java類庫(kù),本文主要介紹了如何利用itext實(shí)現(xiàn)html轉(zhuǎn)PDF,需要的可以參考下2024-03-03Java 數(shù)組獲取最大和最小值的實(shí)例實(shí)現(xiàn)
這篇文章主要介紹了Java 數(shù)組獲取最大和最小值的實(shí)例實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Java用BigDecimal類解決Double類型精度丟失的問(wèn)題
這篇文章主要介紹了Java用BigDecimal類解決Double類型精度丟失的問(wèn)題,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-12-12Mybatis返回單個(gè)實(shí)體或者返回List的實(shí)現(xiàn)
這篇文章主要介紹了Mybatis返回單個(gè)實(shí)體或者返回List的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07前后端項(xiàng)目分離解決cors錯(cuò)誤的方法詳解
隨著前后端分離技術(shù)的越來(lái)越盛行,跨域問(wèn)題也逐漸凸顯了出來(lái),下面這篇文章主要給大家介紹了關(guān)于前后端項(xiàng)目分離解決cors錯(cuò)誤的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02必須掌握的十個(gè)Lambda表達(dá)式簡(jiǎn)化代碼提高生產(chǎn)力
這篇文章主要為大家介紹了必須掌握的十個(gè)Lambda表達(dá)式來(lái)簡(jiǎn)化代碼提高生產(chǎn)力,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04java對(duì)象list使用stream根據(jù)某一個(gè)屬性轉(zhuǎn)換成map的3種方式舉例
開(kāi)發(fā)小伙伴們通常會(huì)需要使用到對(duì)象和Map互相轉(zhuǎn)換的開(kāi)發(fā)場(chǎng)景,下面這篇文章主要給大家介紹了關(guān)于java對(duì)象list使用stream根據(jù)某一個(gè)屬性轉(zhuǎn)換成map的3種方式,需要的朋友可以參考下2024-01-01SpringCloud turbine監(jiān)控實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了SpringCloud turbine監(jiān)控實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12springboot項(xiàng)目使用SchedulingConfigurer實(shí)現(xiàn)多個(gè)定時(shí)任務(wù)的案例代碼
這篇文章主要介紹了springboot項(xiàng)目使用SchedulingConfigurer實(shí)現(xiàn)多個(gè)定時(shí)任務(wù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01