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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時間:2023/12/10 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “Transaction rolled back because it has been marked as rollback-only” 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

spring的聲明事務(wù)提供了強(qiáng)大功能,讓我們把業(yè)務(wù)關(guān)注和非業(yè)務(wù)關(guān)注的東西又分離開了。好東西的使用,總是需要有代價(jià)的。使用聲明事務(wù)的時候,一 個不小心經(jīng)常會碰到“Transaction rolled back because it has been marked as rollback-only”這個異常。有時候又常常會納悶,"我已經(jīng)try-catch了,為什么還這樣呢?"

?

Xml代碼 ?
  • <!--?0?placeHolder?-->??
  • <bean??class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">??
  • ????<property?name="locations">??
  • ????????<list>??
  • ????????????<value>files/pro.properties</value>??
  • ????????</list>??
  • ????</property>??
  • </bean>??
  • ??
  • <!--?1?dataSource?-->??
  • <bean?id="dataSource"?class="org.springframework.jdbc.datasource.DriverManagerDataSource">??
  • ????<property?name="driverClassName"?value="com.mysql.jdbc.Driver"></property>??
  • ????<property?name="url"?value="${jdbc.mysql.url}"></property>??
  • ????<property?name="username"?value="${jdbc.username}"></property>??
  • ????<property?name="password"?value="${jdbc.userpassword}"></property>??
  • </bean>??
  • ??
  • <!--?2?jdbcTemplate?-->??
  • <bean?id="jdbcTemplate"?class="org.springframework.jdbc.core.JdbcTemplate">??
  • ????<property?name="dataSource"?ref="dataSource"></property>??
  • </bean>??
  • ??
  • <!--?3?BaseDao?-->??
  • <bean?id="baseDao"?class="transaction.dao.BaseDao"?abstract="true">??
  • ????<property?name="jdbcTemplate"?ref="jdbcTemplate"?/>??
  • </bean>??
  • ??
  • <bean?id="aDao"?class="transaction.dao.Adao"?parent="baseDao">??
  • </bean>??
  • ??
  • <bean?id="bDao"?class="transaction.dao.Bdao"?parent="baseDao">???
  • </bean>??
  • ??
  • <!--?4?service?-->??
  • <bean?id="aBo"?class="transaction.bo.AboImpl">??
  • ????<property?name="aDao"?ref="aDao"?/>??
  • ????<property?name="bBo"?ref="bBo"?/>??
  • </bean>??
  • ??
  • <bean?id="bBo"?class="transaction.bo.BboImpl">??
  • ????<property?name="bDao"?ref="bDao"?/>??
  • </bean>??
  • ??
  • <!--?5?transaction?-->??
  • <bean?id="transactionManager"?class="org.springframework.jdbc.datasource.DataSourceTransactionManager">??
  • ????<property?name="dataSource"?ref="dataSource"?/>??
  • </bean>??
  • ??
  • <bean?id="transactionInterceptor1"?class="org.springframework.transaction.interceptor.TransactionInterceptor"?>??
  • ????<property?name="transactionManager"?ref="transactionManager"></property>??
  • ????<property?name="transactionAttributes">??
  • ????????<props>??
  • ????????????<prop?key="*">PROPAGATION_REQUIRED</prop>??
  • ????????</props>????
  • ????</property>??
  • </bean>??
  • ??
  • <bean?id="autoProxy1"??class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
  • ????<property?name="beanNames">??
  • ????????<list>??
  • ????????????<value>*Bo</value>??
  • ????????</list>??
  • ????</property>??
  • ????<property?name="interceptorNames">??
  • ????????<list>??
  • ????????<!--???
  • ????????????<value>transactionInterceptor2</value>?
  • ????????????-->??
  • ????????????<value>transactionInterceptor1</value>????
  • ????????</list>??
  • ????</property>??
  • </bean>??
  • ?這里的聲明事務(wù)是作用于所有以Bo為后綴的bean的所有方法上,使用REQUIRED傳播方式。

    Java代碼 ?
  • public?int?insertA(A?a)???
  • {??
  • ????aDao.insertA(a);??
  • ??????
  • ????B?b?=?new?B();??
  • ????b.setName("bbb");??
  • ????try??
  • ????{??
  • ????????bBo.insertB(b);??
  • ????}??
  • ????catch(Exception?e)??
  • ????{??
  • ????????System.out.println("aaa");??
  • ????}??
  • ????return?0;??
  • }??
  • ?這里,insertA 開始一個事務(wù),調(diào)用aDao.insertA(a)[一個簡單的數(shù)據(jù)庫操作],然后調(diào)用 bBo.insertB(b)[bo調(diào)dao,dao直接拋異常]。bBo的insertB方法,也要開始一個事務(wù),但是這里的傳播機(jī)制是 REQUIRED。OK,和insertA 的事務(wù)合二為一吧。因?yàn)閎Bo.insertB(b)會拋異常出來,這里try-catch下,希望aDao.insertA(a)的操作能夠成功。

    但是現(xiàn)實(shí)總是殘酷的,這里會有一個大大的 “Transaction rolled back because it has been marked as rollback-only” ,結(jié)果你會發(fā)現(xiàn)aDao.insertA(a)的操作也沒有成功。

    ?

    try-catch不起作用的原因簡單的說就是,try-catch的不是地方,你認(rèn)為你的try-catch是最接近異常拋出點(diǎn)了,是第一個處理 的handler了。實(shí)際上,spring在更早一步就try-catch 住了,同時還設(shè)置了一些標(biāo)志位,再把catch住的異常往外拋。這個時候才是我們的try-catch。而"Transaction rolled back because it has been marked as rollback-only"就是因?yàn)槭聞?wù)在提交的時候,發(fā)現(xiàn)標(biāo)志位已經(jīng)被設(shè)置了,不應(yīng)該去提交了,然后吭哧吭哧的回滾調(diào),再提示你已經(jīng)被設(shè)置成 rollback-only了。

    ?

    原因是既然如此,那么在不改變代碼的情況下,依靠配置能否解決這個問題呢?使用PROPAGATION_REQUIRES_NEW吧。對于 bBo.insertB(b)開個新的事務(wù),如果失敗了就回滾調(diào),不影響外面的insertA不就OK了。最簡單的情況就是在 transactionInterceptor1前面,再加個攔截器transactionInterceptor2,該攔截器只針對insertB的事 務(wù)屬性進(jìn)行修改。

    Xml代碼 ?
  • <bean?id="autoProxy1"??class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
  • ????<property?name="beanNames">??
  • ????????<list>??
  • ????????????<value>*Bo</value>??
  • ????????</list>??
  • ????</property>??
  • ????<property?name="interceptorNames">??
  • ????????<list>??
  • ???????????
  • ????????????<value>transactionInterceptor2</value>??
  • ??????????????
  • ????????????<value>transactionInterceptor1</value>????
  • ????????</list>??
  • ????</property>??
  • </bean>??
  • ??
  • ??
  • <bean?id="transactionInterceptor2"?class="org.springframework.transaction.interceptor.TransactionInterceptor"?>??
  • ????<property?name="transactionManager"?ref="transactionManager"></property>??
  • ????<property?name="transactionAttributes">??
  • ????????<props>??
  • ????????????<prop?key="insertB">PROPAGATION_REQUIRES_NEW</prop>??
  • ????????</props>????
  • ????</property>??
  • </bean>??
  • 注意interceptorNames里面元素的位置。先要使用transactionInterceptor2,再使用 transactionInterceptor1.因?yàn)檎{(diào)用insertB的時候,transactionInterceptor2先開了一個新事務(wù),而 后transactionInterceptor1融合進(jìn)這個事務(wù)。如果這2個攔截器的順序顛倒的話,那么還是會出現(xiàn)“Transaction rolled back because it has been marked as rollback-only”。因?yàn)?#xff0c;transactionInterceptor2生成事務(wù)回滾以后,還是會把ex拋給 transactionInterceptor1。這個時候,transactionInterceptor1的事務(wù)和insertA的事務(wù)是同一個。 transactionInterceptor1,把標(biāo)志設(shè)置好,等到insertA真的結(jié)束的時候,因?yàn)楫惓1晃覀兊膖ry-catch捕獲 了,spring就會發(fā)現(xiàn)需要提交的事務(wù)具有一個已經(jīng)被標(biāo)記號的rollback。所以就又拋出來了。

    ?

    但是如果系統(tǒng)有很多遺留的因素導(dǎo)致你不敢盲目的修改配置文件的話(比如事務(wù)的poincut),那么我們就再加一個事務(wù)proxy就OK了。

    Xml代碼 ?
  • <bean?id="autoProxy2"?class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
  • ????????<property?name="beanNames">??
  • ????????????<list>??
  • ????????????????<value>*Bo</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????????<value>transactionInterceptor2</value>??
  • ????????????????<!--???
  • ????????????????<value>transactionInterceptor1</value>???
  • ????????????????-->??
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??
  • ??????
  • ????<bean?id="autoProxy1"??class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
  • ????????<property?name="beanNames">??
  • ????????????<list>??
  • ????????????????<value>*Bo</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????<value>transactionInterceptor1</value>????
  • ????????????<!--???
  • ????????????<value>transactionInterceptor2</value>???????
  • ????????????-->????????
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??
  • 如上的配置還是會帶來悲劇的“Transaction rolled back because it has been marked as rollback-only”。

    ?

    但是如果我們把 autoProxy2 放到 autoProxy1 或者給自動代理加上順序的話。。。結(jié)果就是喜劇了。。

    Xml代碼 ?
  • <bean?id="autoProxy1"??class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
  • ????????<property?name="beanNames">??
  • ????????????<list>??
  • ????????????????<value>*Bo</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????<value>transactionInterceptor1</value>????
  • ????????????<!--???
  • ????????????<value>transactionInterceptor2</value>???????
  • ????????????-->????????
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??
  • ??????
  • ??????
  • ????<bean?id="autoProxy2"?class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
  • ????????<property?name="beanNames">??
  • ????????????<list>??
  • ????????????????<value>*Bo</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????????<value>transactionInterceptor2</value>??
  • ????????????????<!--???
  • ????????????????<value>transactionInterceptor1</value>???
  • ????????????????-->??
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??
  • ?

    ?

    造成這個原因是由使用了2個代理的順序?qū)е碌摹?/p>

    在做自動代理的時候,spring會按照postBeanProcessor bean聲明的順序(如果沒有設(shè)置順序的話),來依次處理bean。如果autoProxy2 在 autoProxy1 之前,這樣transactionInterceptor2 就會更加貼近insertB的調(diào)用,其效果就像

    Xml代碼 ?
  • <bean?id="autoProxy1"??class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">??
  • ????????<property?name="beanNames">??
  • ????????????<list>??
  • ????????????????<value>*Bo</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????<value>transactionInterceptor1</value>????
  • ???????????
  • ????????????<value>transactionInterceptor2</value>????????
  • ??????????????????
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??
  • ?的配置。

    ?

    ?

    看來~~~ spring 還是要注意bean的順序啊,哈哈哈。。。

    轉(zhuǎn)載于:https://www.cnblogs.com/langtianya/p/4962784.html

    總結(jié)

    以上是生活随笔為你收集整理的“Transaction rolled back because it has been marked as rollback-only”的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。