1. 程式人生 > >Transaction rolled back because it has been marked as rollback-only分析解決方法

Transaction rolled back because it has been marked as rollback-only分析解決方法

1.

Transaction rolled back because it has been marked as rollback-only
事務已回滾,因為它被標記成了只回滾
<prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
query開頭的方法readOnly,所以只能select,丟擲異常,insert/update/delete操作必然回滾

2.

發現selectA呼叫selectB,如果selectB丟擲Exception,selectA中捕獲Exception但是並不繼續向外丟擲,最後會出現錯誤。


糾其原理其實很簡單,在selectB返回的時候,transaction被設定為rollback-only了,但是selectA正常消化掉,沒有繼續向外拋。
那麼selectA結束的時候,transaction會執commit操作,但是 transaction已經被設定為 rollback-only了。
所以會出現這個錯誤。
有的同學說了,那不是沒得搞了,service不能丟擲異常,或者不能攔截異常了?
其實不然,其實錯誤不在這裡,而是select這種操作為什麼要啟動事務呢?

3.demo示例程式碼

1.applicationContext.xml配置事務

<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- <tx:method name="sendIllegalMessage" read-only="false" rollback-for="Exception" propagation="REQUIRES_NEW" /> -->
            <
tx:method name="get*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="load*" read-only="true" /> <tx:method name="query*" read-only="true" /> <tx:method name="add*" read-only="false" rollback-for="Exception"
propagation="REQUIRED" /> <tx:method name="batchAdd*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="save*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="insert*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="update*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="modify*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="delete*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="del*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="registe*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="approve*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="clear*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="set*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="reset*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="getUpdate*" read-only="false" rollback-for="Exception" propagation="REQUIRED" /> <tx:method name="updatedQuery*" read-only="false" rollback-for="Exception" propagation="REQUIRES_NEW" /> <!-- <tx:method name="*" read-only="true"/> --> </tx:attributes> </tx:advice>
<aop:config>
        <aop:advisor pointcut="execution(* com.xxx.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.v30.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.v31.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.v33.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.v34.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.limitCoupon.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.v35.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.v36.service..*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.auth.*Service.*(..))" advice-ref="txAdvice"/>
        <aop:advisor pointcut="execution(* com.xxx.notify.*Service.*(..))" advice-ref="txAdvice"/>
    </aop:config>

2.junit測試程式碼

@Test
    public void testCancelTask2(){
        try {
            transService.updateTransCancel2();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
public void updateTransCancel2() {
        int upCount = transMapper.updateTransCancelStat(520657512071l, 1, 0, 0,-1,-1,-1,-1,-1,-1);
        try {
            cancelTransSendSms.cancelTransSendSms2();
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info("upCount="+upCount);
        
    }

public void cancelTransSendSms2() throws Exception{
        aotoCancel2();
    }


    private void aotoCancel2() {
        txtMap=smsConverUtil.getMessage(smsParamsMap, "RenterNoAuthDeposite", "RenterNoAuthDeposite0000");
    }

public Map<String,String> getMessage(Map<String,Object> smsParamsMap,String smsContentKey,String pushKey){
            Map<String,String> map=new LinkedHashMap<String, String>();
            String smsContent="";
            String jpushContent="";
            String smsMessage="";
            String flag="";
            logger.info("in rentNo->smsContentKey is {}",smsContentKey);
            if(StringUtils.isNotBlank(smsContentKey)){
                smsContent=getContent(smsParamsMap,smsContentKey);
                smsMessage=smsMsgDescMap.get(smsContentKey);
            }
            if(StringUtils.isNotBlank(pushKey)){
                jpushContent=getPushContentTemplate(pushKey,smsParamsMap);
                flag=pushMsgFlagMap.get(pushKey);
            }
            map.put("smsContent",smsContent);
            map.put("jpushContent",jpushContent);
            map.put("smsMessage",smsMessage);
            map.put("flag",flag);
            return map;
        }

private String getPushContentTemplate(String contentKey,Map<String,Object> contentParamMap){
            try {
                String templateContent = operationService.getTemplateMsgByAppTypeAndCode(AppTypeConstant.JPUSH, contentKey);
                if(StringUtils.isEmpty(templateContent)){
                    return  null;
                }
                
                return replaceTemplateContent(templateContent,contentParamMap);
                
            } catch (Exception e) {
                logger.error("推送訊息獲取訊息內容報錯!",e);
            }
            return null;
        }
public String getTemplateMsgByAppTypeAndCode(String appType, String textCode) {
         
        try {
            return operationTextCache.getUpdateOperateTextMsgByAppTypeAndTextCode(appType, textCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return null;
    }
    
    public String tgetTemplateMsgByAppTypeAndCode(String appType, String textCode) {
         
        return operationTextCache.tfindOperateTextMsgByAppTypeAndTextCode(appType, textCode);
    }
public String findOperateTextMsgByAppTypeAndTextCode(String appType,
            String textCode) {
        OperationText operationText = this.findOperationTextByAppTypeAndTextCode(appType, textCode);
        if (operationText==null) {
            throw new IllegalArgumentException("appType:"+appType+","+"textCode:"+textCode+",不存在文字模板訊息");
        }else {
            return operationText.getTextMsg();
        }
    }
    
    public String getUpdateOperateTextMsgByAppTypeAndTextCode(String appType,
            String textCode) {
        OperationText operationText = this.findOperationTextByAppTypeAndTextCode(appType, textCode);
        if (operationText==null) {
            throw new IllegalArgumentException("appType:"+appType+","+"textCode:"+textCode+",不存在文字模板訊息");
        }else {
            return operationText.getTextMsg();
        }
    }
    
    public String tfindOperateTextMsgByAppTypeAndTextCode(String appType,
            String textCode) {
        OperationText operationText = this.findOperationTextByAppTypeAndTextCode(appType, textCode);
        if (operationText==null) {
            throw new IllegalArgumentException("appType:"+appType+","+"textCode:"+textCode+",不存在文字模板訊息");
        }else {
            return operationText.getTextMsg();
        }
    }

4.彙總(A呼叫B)

4.1 A無事務,B無事務(將find,get改成tfind,tget方法名)  A不回滾,不報以上錯誤。

4.2 A無事務,B get,find只讀事務,但是不丟擲throw new IllegalArgumentException("appType:"+appType+","+"textCode:"+textCode+",不存在文字模板訊息");   A不回滾,不報以上錯誤。

4.3 A update事務,B get,find只讀事務且丟擲異常 (間隔捕獲)   A回滾,報以上錯誤。

4.4 A無事務,B get,find只讀事務且丟擲異常  (間隔捕獲)          A回滾,報以上錯誤。

4.5 A update事務,B update事務且丟擲異常 (間隔捕獲)          A回滾,報以上錯誤。

4.6 A update事務,B update事務且丟擲異常且try..catch..B   A不回滾,不報以上錯誤。

4.6 A無事務,B update事務且丟擲異常且try..catch..B           A不回滾,不報以上錯誤。

簡單而言之:

方法1有try,方法2無try,方法3 find或get throws  A回滾,報以上錯誤。    捕獲的異常有間隔有問題。

方法1有try,方法2有try,方法3 find或get throws  A不回滾,不報以上錯誤。 在丟擲異常的上一級方法捕獲沒有問題。

基於以上的情況說明:類1方法1無事務,類2方法2有事務get/find無捕獲,類3方法3無事務 --->報rollback-only錯誤。

基於以上的情況說明:類1方法1無事務,類2方法2有事務get/find有捕獲,類3方法3無事務 --->不報rollback-only錯誤。     上文說的間隔try

 類1方法1無事務,類2方法2有事務get/find有無捕獲,類3方法3有事務 --->報rollback-only錯誤。 被spring標記了rollback位,這就是為什麼要REQUIRES_NEW事務了。

類1方法1無事務,類2方法2有事務updatedQuery新建事務有捕獲,類3方法3有事務 --->不報rollback-only錯誤。

類1方法1無事務,類2方法2有事務updatedQuery新建事務無捕獲,類3方法3有事務 --->報rollback-only錯誤。

相關推薦

Transaction rolled back because it has been marked as rollback-only分析解決方法

1. Transaction rolled back because it has been marked as rollback-only事務已回滾,因為它被標記成了只回滾<prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>q

Transaction rolled back because it has been marked as rollback-only

解決辦法 框架 捕獲 back 結束 tro 接口 lba -o 出現這種錯誤的原因 1.接口A 調用了接口B 2.接口B報異常了,沒有在B裏面進行try catch捕獲 3.接口A對 接口B進行了try catch捕獲 因為接口B報異常 會把當前事物A接口的事物(如果B沒

Transaction rolled back because it has been marked as rollback-only解決方案

預設spring事務只在發生未被捕獲的 runtimeexcetpion時才回滾。spring aop 異常捕獲原理:被攔截的方法需顯式丟擲異常,並不能經任何處理,這樣aop代理才能捕獲到方法的異常,才能進行回滾,預設情況下aop只捕獲runtimeexcep

Srping Transaction rolled back because it has been marked as rollback-only解決方案

1.異常相關描述 如題,此異常的全部資訊如下: org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked a

使用composer提示[ErrorException ]proc_get_status() has been disabled for security reasons 的解決方法

從錯誤提示資訊中可以看到是因為關閉了PHP的proc_get_status()函式,那麼如何解決這個問題呢? 開啟php.ini檔案,搜尋 disable_functions,找到如下類似內容: disable_functions=passthru,exec,system,chroot

spring事務(Transaction )報 marked as rollback-only異常的原因及解決方法

很多朋友在使用spring+hibernate或mybatis等框架時經常遇到報Transaction rolled back because it has been marked as rollback-only的異常,這個異常是怎麼造成的 呢,下面將給大家進行詳細的分析。 &nbs

Spring-Boot 出現Transaction marked as rollback only異常

最近在開發的過程中遇到了使用Transaction marked as rollback only的問題,瞭解到報錯的原因: 應該是事務被rollback了多次導致的錯誤。仔細看程式碼,由於專案中在aop切面、控制層、service分別開啟了一次事務,而

NotImplementedError: fromstring() has been removed. Please call frombytes() instead.解決方法

from VideoCapture import Device import time, string interval = 2 cam = Device(devnum=0, showVideoWindow=0) # cam.setResolution(648, 480

Transaction marked as rollback-only異常

1、當整個方法中每個子方法沒報錯時,整個方法執行完才提交事務,如果某個子方法有異常,spring將該事務標

XCode warning:“View Controller” is unreachable because it has no entry points

ins warning 指針 xcod tro 方案 ant access 不能 Unsupported Configuration: “View Controller” is unreachable because it has no entry points, and

VS2017 community創建模板錯誤 The document cannot be opened. It has been renamed, deleted or moved

nbsp rom ng- 模板生成 sfm visual mat block ati 當我使用我自己創建的模板生成工程,打開文件時,會出現“The document cannot be opened. It has been renamed, deleted or move

Type '' cannot conform to protocol '' because it has requirements that cannot be satisfied

jcp eth clas onf block some 編譯器 conf @class 我有一個Objective-C協議,我試圖在Swift類中實現。例如: @class AnObjcClass; @protocol ObjcProtocol <NSObjec

SparkException: Could not find CoarseGrainedScheduler or it has been stopped.

org.apache.spark.SparkException: Could not find CoarseGrainedScheduler or it has been stopped. at org.apache.spark.rpc.netty.Dispatcher.postMess

spring 丟擲自定義異常報java.lang.RuntimeException: org.apache.cxf.interceptor.Fault: Transaction rolled back

介紹一下我報這個錯誤造成的原因:    我啟用了aop全域性事務管理,但是我在業務程式碼中自定義了一個異常類繼承了Exception,當我需要在指定位置丟擲這個異常的時候,就會報:java.lang.RuntimeException: org.apache.cxf.inter

java.lang.IllegalStateException: Unable to open nested entry 'lib/bsfit-api-1.0.3.jar'. It has been

java.lang.IllegalStateException: Unable to open nested entry 'lib/bsfit-api-1.0.3.jar'.  It has been compressed and nested jar files must

weex開發 - 載入index.js崩潰,白屏(may it has been destroyed so method:fireEvent is ignored,Url must be passe)

最近,博主在做weex專案中發現了一個奇怪的問題,分別會報如下幾個錯誤: 1.[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0

UnexpectedRollbackException: Transaction rolled back 關於失誤自動回滾的問題

完整的異常資訊:  org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-onl

no schema has been selected to create in … error 解決方案

  What is the search path? Per documentation: [...] tables are often referred to by unqualified names, which consist of just the

Warning[Pe301]: typedef name has already been declared (with same type)問題解決方法

最近遇到一個警告問題,一直解決不了,網上也查閱了很多文章,都沒有講述具體的解決方法。 今天除錯程式,偶然發現一個現象,基於這個現象,分析該警告的可能原因如下: 首先,我是新建了一個main.h檔案,裡面包含所有的需要的標頭檔案,但在其中的一個檔案裡,我定義了一個結構型別; te

x509: cannot validate certificate for x.x.x.x because it doesn't contain any IP SANs 解決:

x509: cannot validate certificate for x.x.x.x because it doesn't contain any IP SANs 解決: 一, 編輯openssl.cnf,在[v3_ca]下面新增:subjectAltName = IP:IP地址 &nb