Spring中propagation的7種事務(wù)配置及說明
Spring propagation7種事務(wù)配置
1、簡(jiǎn)述
在聲明式的事務(wù)處理中,要配置一個(gè)切面,其中就用到了propagation,表示打算對(duì)這些方法怎么使用事務(wù),是用還是不用,其中propagation有七種配置,REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。默認(rèn)是REQUIRED。
2、Spring中七種Propagation類的事務(wù)屬性詳解:
REQUIRED
:支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就新建一個(gè)事務(wù)。這是最常見的選擇。
SUPPORTS
:支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。
MANDATORY
:支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就拋出異常。
REQUIRES
_NEW:新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。
NOT_SUPPORTED
:以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。
NEVER
:以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
NESTED
:支持當(dāng)前事務(wù),如果當(dāng)前事務(wù)存在,則執(zhí)行一個(gè)嵌套事務(wù),如果當(dāng)前沒有事務(wù),就新建一個(gè)事務(wù)。
3、注意事項(xiàng)
這些配置將影響數(shù)據(jù)存儲(chǔ),必須根據(jù)情況選擇。
@Transactional事務(wù)幾點(diǎn)注意及其屬性Propagation的使用
@Transactional事務(wù)幾點(diǎn)注意
這里面有幾點(diǎn)需要大家留意:
A. 一個(gè)功能是否要事務(wù),必須納入設(shè)計(jì)、編碼考慮。不能僅僅完成了基本功能就ok。
B. 如果加了事務(wù),必須做好開發(fā)環(huán)境測(cè)試(測(cè)試環(huán)境也盡量觸發(fā)異常、測(cè)試回滾),確保事務(wù)生效。
C. 以下列了事務(wù)使用過程的注意事項(xiàng),請(qǐng)大家留意。
1. 不要在接口上聲明@Transactional ,而要在具體類的方法上使用 @Transactional 注解,否則注解可能無效。
2.不要圖省事,將@Transactional放置在類級(jí)的聲明中,放在類聲明,會(huì)使得所有方法都有事務(wù)。故@Transactional應(yīng)該放在方法級(jí)別,不需要使用事務(wù)的方法,就不要放置事務(wù),比如查詢方法。否則對(duì)性能是有影響的。
3.使用了@Transactional的方法,對(duì)同一個(gè)類里面的方法調(diào)用, @Transactional無效。比如有一個(gè)類Test,它的一個(gè)方法A,A再調(diào)用Test本類的方法B(不管B是否public還是private),但A沒有聲明注解事務(wù),而B有。則外部調(diào)用A之后,B的事務(wù)是不會(huì)起作用的。(經(jīng)常在這里出錯(cuò))
4.使用了@Transactional的方法,只能是public,@Transactional注解的方法都是被外部其他類調(diào)用才有效,故只能是public。道理和上面的有關(guān)聯(lián)。故在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會(huì)報(bào)錯(cuò),但事務(wù)無效。
5.經(jīng)過在ICORE-CLAIM中測(cè)試,效果如下:
A.拋出受查異常XXXException,事務(wù)會(huì)回滾。
B.拋出運(yùn)行時(shí)異常NullPointerException,事務(wù)會(huì)回滾。
C.Quartz中,execute直接調(diào)用加了@Transactional方法,可以回滾;間接調(diào)用,不會(huì)回滾。(即上文3點(diǎn)提到的)
D.異步任務(wù)中,execute直接調(diào)用加了@Transactional方法,可以回滾;間接調(diào)用,不會(huì)回滾。(即上文3點(diǎn)提到的)
E.在action中加上@Transactional,不會(huì)回滾。切記不要在action中加上事務(wù)。
F.在service中加上@Transactional,如果是action直接調(diào)該方法,會(huì)回滾,如果是間接調(diào),不會(huì)回滾。(即上文3提到的)
G.在service中的private加上@Transactional,事務(wù)不會(huì)回滾。
其屬性Propagation的使用:
Spring Transaction中有一個(gè)很重要的屬性:Propagation。主要用來配置當(dāng)前需要執(zhí)行的方法,與當(dāng)前是否有transaction之間的關(guān)系。
我曉得有點(diǎn)兒抽象,這也是為什么我想要寫這篇博客的原因。看了后面的例子,大家應(yīng)該就明白了。
一、Propagation取值:
REQUIRED
(默認(rèn)值):在有transaction狀態(tài)下執(zhí)行;如當(dāng)前沒有transaction,則創(chuàng)建新的transaction;
SUPPORTS
:如當(dāng)前有transaction,則在transaction狀態(tài)下執(zhí)行;如果當(dāng)前沒有transaction,在無transaction狀態(tài)下執(zhí)行;
MANDATORY
:必須在有transaction狀態(tài)下執(zhí)行,如果當(dāng)前沒有transaction,則拋出異常IllegalTransactionStateException;
REQUIRES_NEW
:創(chuàng)建新的transaction并執(zhí)行;如果當(dāng)前已有transaction,則將當(dāng)前transaction掛起;
NOT_SUPPORTED
:在無transaction狀態(tài)下執(zhí)行;如果當(dāng)前已有transaction,則將當(dāng)前transaction掛起;
NEVER
:在無transaction狀態(tài)下執(zhí)行;如果當(dāng)前已有transaction,則拋出異常IllegalTransactionStateException。
二、REQUIRED與REQUIRED_NEW
上面描述的6種propagation屬性配置中,最難以理解,并且容易在transaction設(shè)計(jì)時(shí)出現(xiàn)問題的是REQUIRED和REQURED_NEW這兩者的區(qū)別。當(dāng)程序在某些情況下拋出異常時(shí),如果對(duì)于這兩者不夠了解,就可能很難發(fā)現(xiàn)而且解決問題。
下面我們給出三個(gè)場(chǎng)景進(jìn)行分析:
場(chǎng)景一:
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"); } }
這種情況下,我們只需要在調(diào)用ServiceA.callB時(shí)捕獲ServiceB中拋出的運(yùn)行時(shí)異常,則transaction就會(huì)正常的rollback。
場(chǎng)景二
在保持場(chǎng)景一中ServiceB不變,在ServiceA中調(diào)用ServiceB的doSomething時(shí)去捕獲這個(gè)異常,如下:
public class ServiceA { @Transactional public void callB() { try { serviceB.doSomething(); } catch (RuntimeException e) { System.err.println(e.getMessage()); } } }
這個(gè)時(shí)候,我們?cè)僬{(diào)用ServiceA的callB。程序會(huì)拋出org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only這樣一個(gè)異常信息。原因是什么呢?
因?yàn)樵赟erviceA和ServiceB中的@Transactional propagation都采用的默認(rèn)值:REQUREID。
根據(jù)我們前面講過的REQUIRED特性,當(dāng)ServiceA調(diào)用ServiceB的時(shí)候,他們是處于同一個(gè)transaction中。
如下圖所示:
當(dāng)ServiceB中拋出了一個(gè)異常以后,ServiceB會(huì)把當(dāng)前的transaction標(biāo)記為需要rollback。
但是ServiceA中捕獲了這個(gè)異常,并進(jìn)行了處理,認(rèn)為當(dāng)前transaction應(yīng)該正常commit。
此時(shí)就出現(xiàn)了前后不一致,也就是因?yàn)檫@樣,拋出了前面的UnexpectedRollbackException。
場(chǎng)景三
在保持場(chǎng)景二中ServiceA不變,修改ServiceB中方法的propagation配置為REQUIRES_NEW,如下:
public class ServiceB { @Transactional(propagation = Propagation.REQUIRES_NEW) public void doSomething() { throw new RuntimeException("B throw exception"); } }
此時(shí),程序可以正常的退出了,也沒有拋出UnexpectedRollbackException。原因是因?yàn)楫?dāng)ServiceA調(diào)用ServiceB時(shí),serviceB的doSomething是在一個(gè)新的transaction中執(zhí)行的。
如下圖所示:
所以,當(dāng)doSomething拋出異常以后,僅僅是把新創(chuàng)建的transaction rollback了,而不會(huì)影響到ServiceA的transaction。
ServiceA就可以正常的進(jìn)行commit。
當(dāng)然這里把ServiceA和ServiceB放在兩個(gè)獨(dú)立的transaction是否成立,還需要再多多考慮你的業(yè)務(wù)需求。
Transaction不是一個(gè)新東西了,那對(duì)于transaction的使用會(huì)不會(huì)有一些模式?一些經(jīng)驗(yàn)之談呢?答案肯定是有的,以后再說。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot 添加MySQL數(shù)據(jù)庫及JPA實(shí)例
本篇文章主要介紹了Spring Boot 添加MySQL數(shù)據(jù)庫及JPA,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03Eclipse手動(dòng)導(dǎo)入DTD文件實(shí)現(xiàn)方法解析
這篇文章主要介紹了Eclipse手動(dòng)導(dǎo)入DTD文件實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10如何修改nacos權(quán)重報(bào)錯(cuò)問題
這篇文章主要介紹了如何修改nacos權(quán)重報(bào)錯(cuò)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07Spring核心容器之ApplicationContext上下文啟動(dòng)準(zhǔn)備詳解
這篇文章主要介紹了Spring核心容器之ApplicationContext上下文啟動(dòng)準(zhǔn)備詳解,ApplicationContext 繼承自 BeanFactory ,其不僅包含 BeanFactory 所有功能,還擴(kuò)展了容器功能,需要的朋友可以參考下2023-11-11Java利用for循環(huán)輸出空心三角形、空心菱形和空心矩形的代碼
今天小編就為大家分享一篇關(guān)于Java利用for循環(huán)輸出空心三角形、空心菱形和空心矩形的代碼,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12SpringBoot集成tensorflow實(shí)現(xiàn)圖片檢測(cè)功能
TensorFlow名字的由來就是張量(Tensor)在計(jì)算圖(Computational?Graph)里的流動(dòng)(Flow),它的基礎(chǔ)就是前面介紹的基于計(jì)算圖的自動(dòng)微分,本文將給大家介紹Spring?Boot集成tensorflow實(shí)現(xiàn)圖片檢測(cè)功能,需要的朋友可以參考下2024-06-06java實(shí)現(xiàn)簡(jiǎn)單的加減乘除計(jì)算器
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的加減乘除計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09