“Transaction rolled back because it has been marked as rollback-only”
spring的聲明事務(wù)提供了強(qiáng)大功能,讓我們把業(yè)務(wù)關(guān)注和非業(yè)務(wù)關(guān)注的東西又分離開了。好東西的使用,總是需要有代價的。使用聲明事務(wù)的時候,一 個不小心經(jīng)常會碰到“Transaction rolled back because it has been marked as rollback-only”這個異常。有時候又常常會納悶,"我已經(jīng)try-catch了,為什么還這樣呢?"
?
Xml代碼 ??這里的聲明事務(wù)是作用于所有以Bo為后綴的bean的所有方法上,使用REQUIRED傳播方式。
Java代碼 ??這里,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代碼 ?注意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代碼 ?如上的配置還是會帶來悲劇的“Transaction rolled back because it has been marked as rollback-only”。
?
但是如果我們把 autoProxy2 放到 autoProxy1 或者給自動代理加上順序的話。。。結(jié)果就是喜劇了。。
Xml代碼 ??
?
造成這個原因是由使用了2個代理的順序?qū)е碌摹?/p>
在做自動代理的時候,spring會按照postBeanProcessor bean聲明的順序(如果沒有設(shè)置順序的話),來依次處理bean。如果autoProxy2 在 autoProxy1 之前,這樣transactionInterceptor2 就會更加貼近insertB的調(diào)用,其效果就像
Xml代碼 ??的配置。
?
?
看來~~~ 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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构:字典
- 下一篇: Blog-LOGO原型