溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

spring中@Transactional 無(wú)效如何解決

發(fā)布時(shí)間:2021-06-11 15:34:04 來(lái)源:億速云 閱讀:245 作者:Leah 欄目:編程語(yǔ)言

今天就跟大家聊聊有關(guān)spring中@Transactional 無(wú)效如何解決,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

1 .在需要事務(wù)管理的地方加@Transactional 注解。@Transactional 注解可以被應(yīng)用于接口定義和接口方法、類定義和類的 public 方法上 。

2 . @Transactional 注解只能應(yīng)用到 public 可見(jiàn)度的方法上 。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會(huì)報(bào)錯(cuò), 但是這個(gè)被注解的方法將不會(huì)展示已配置的事務(wù)設(shè)置。

3 . 注意僅僅 @Transactional 注解的出現(xiàn)不足于開(kāi)啟事務(wù)行為,它僅僅 是一種元數(shù)據(jù)。必須在配置文件中使用配置元素,才真正開(kāi)啟了事務(wù)行為。

最近在項(xiàng)目中發(fā)現(xiàn)注解無(wú)效,經(jīng)過(guò)跟蹤源代碼發(fā)現(xiàn)了問(wèn)題,于是在網(wǎng)上找到相同出現(xiàn)此問(wèn)題的人,以下為原文,講解的很詳細(xì):

只要避開(kāi)Spring目前的AOP實(shí)現(xiàn)上的限制,要么都聲明要事務(wù),要么分開(kāi)成兩個(gè)類,要么直接在方法里使用編程式事務(wù)

[問(wèn)題]

Spring的聲明式事務(wù),我想就不用多介紹了吧,一句話“自從用了Spring AOP啊,事務(wù)管理真輕松啊,真輕松;事務(wù)管理代碼沒(méi)有了,腦不酸了,手不痛了,一口氣全配上了事務(wù);輕量級(jí),測(cè)試起來(lái)也簡(jiǎn)單,嘿!”。不管從哪個(gè)角度看,輕量級(jí)聲明式事務(wù)都是一件解放生產(chǎn)力的大好事。所以,我們“一直用它”。

不過(guò),最近的一個(gè)項(xiàng)目里,卻碰到了一個(gè)事務(wù)管理上的問(wèn)題:有一個(gè)服務(wù)類,其一個(gè)聲明了事務(wù)的方法,里面做了三次插入SQL操作,但是在后面出錯(cuò)回滾時(shí),卻發(fā)現(xiàn)前面插入成功了,也是說(shuō),這個(gè)聲明了事務(wù)的方法,實(shí)際上并沒(méi)有真正啟動(dòng)事務(wù)!怎么回事呢?難道Spring的聲明式事務(wù)失效了?

[探幽]

其實(shí)以前也會(huì)碰到有人說(shuō),Spring的事務(wù)配置不起作用,但是根據(jù)第一反應(yīng)和以往經(jīng)驗(yàn),我總會(huì)告訴他,肯定是你的配置有問(wèn)題啦;所以這一次,我想也不會(huì)例外,大概是把事務(wù)注解配在了接口上而不是實(shí)現(xiàn)方法上,或者,如果是用XML聲明方式的話,很可能是切入點(diǎn)的表達(dá)式?jīng)]有配對(duì)。

 不過(guò),在檢查了他們的配置后,卻發(fā)現(xiàn)沒(méi)有配置問(wèn)題,該起事務(wù)的實(shí)現(xiàn)方法上,用了@Transactional事務(wù)注解聲明,XML里也配了注解驅(qū)動(dòng)<tx:annotation-driven .../>,配置很正確啊,怎么會(huì)不起作用?

我很納悶,于是往下問(wèn):

問(wèn)1:其他方法有這種情況么?

答1:沒(méi)有。

問(wèn)2:這個(gè)方法有什么特別的么(以下簡(jiǎn)稱方法B)?

答2:就是調(diào)后臺(tái)插了三條記錄啊,沒(méi)啥特別的。

問(wèn)3:這個(gè)方法是從Web層直接調(diào)用的吧?

答3:不是,是這個(gè)Service類(以下簡(jiǎn)稱ServiceA)的另外一個(gè)方法調(diào)過(guò)來(lái)的(以下簡(jiǎn)稱方法A)。

問(wèn)4:哦,那個(gè)調(diào)用它的方法配了事務(wù)么(問(wèn)題可能在這了)?

 答4:沒(méi)有。

問(wèn)5:那WEB層的Action(用的是Struts2),調(diào)用的是沒(méi)有聲明事務(wù)的方法A,方法A再調(diào)用聲明了事務(wù)的方法B?

答5:對(duì)的。

問(wèn)6:你直接在方法A上加上事務(wù)聲明看看

答6:好。。。

看來(lái)可能找到問(wèn)題所在了,于是把@Transactional也加在方法A上,啟動(dòng)項(xiàng)目測(cè)試,結(jié)果是:事務(wù)正常生效,方法A和方法B都在一個(gè)事務(wù)里了。

好了,現(xiàn)在總結(jié)一下現(xiàn)象:

1、ServiceA類為Web層的Action服務(wù)

2、Action調(diào)用了ServiceA的方法A,而方法A沒(méi)有聲明事務(wù)(原因是方法A本身比較耗時(shí)而又不需要事務(wù))

3、ServiceA的方法A調(diào)用了自己所在class的方法B,而方法B聲明了事務(wù),但是方法B的事務(wù)聲明在這種情況失效了。

4、如果在方法A上也聲明事務(wù),則在Action調(diào)用方法A時(shí),事務(wù)生效,而方法B則自動(dòng)參與了這個(gè)事務(wù)。

我讓他先把A也加上事務(wù)聲明,決定回來(lái)自己再測(cè)一下。

這個(gè)問(wèn)題,表面上是事務(wù)聲明失效的問(wèn)題,實(shí)質(zhì)上很可能是Spring的AOP機(jī)制實(shí)現(xiàn)角度的問(wèn)題。

我想到很久以前研究Spring的AOP實(shí)現(xiàn)時(shí)發(fā)現(xiàn)的一個(gè)現(xiàn)象:對(duì)于以Cglib方式增強(qiáng)的AOP目標(biāo)類,會(huì)創(chuàng)建兩個(gè)對(duì)象,一個(gè)事Bean實(shí)例本身,一個(gè)是Cglib增強(qiáng)代理對(duì)象,而不僅僅是只有后者。我曾經(jīng)疑惑過(guò)這一點(diǎn),但當(dāng)時(shí)沒(méi)有再仔細(xì)探究下去。

 我們知道,Spring的AOP實(shí)現(xiàn)方式有兩種:1、Java代理方式;2、Cglib動(dòng)態(tài)增強(qiáng)方式,這兩種方式在Spring中是可以無(wú)縫自由切換的。

Java代理方式的優(yōu)點(diǎn)是不依賴第三方j(luò)ar包,缺點(diǎn)是不能代理類,只能代理接口。

Spring通過(guò)AopProxy接口,抽象了這兩種實(shí)現(xiàn),實(shí)現(xiàn)了一致的AOP方式:

spring中@Transactional 無(wú)效如何解決 

現(xiàn)在看來(lái),這種抽象同樣帶了一個(gè)缺陷,那就是抹殺了Cglib能夠直接創(chuàng)建普通類的增強(qiáng)子類的能力,Spring相當(dāng)于把Cglib動(dòng)態(tài)生成的子類,當(dāng)普通的代理類了,這也是為什么會(huì)創(chuàng)建兩個(gè)對(duì)象的原因。下圖顯示了Spring的AOP代理類的實(shí)際調(diào)用過(guò)程:

spring中@Transactional 無(wú)效如何解決

因此,從上面的分析可以看出,methodB沒(méi)有被AopProxy通知到, 導(dǎo)致最終結(jié)果是:

被Spring的AOP增強(qiáng)的類,在同一個(gè)類的內(nèi)部方法調(diào)用時(shí),其被調(diào)用方法上的增強(qiáng)通知將不起作用。

而這種結(jié)果,會(huì)造成什么影響呢: 1:內(nèi)部調(diào)用時(shí),被調(diào)用方法的事務(wù)聲明將不起作用 2:換句話說(shuō),你在某個(gè)方法上聲明它需要事務(wù)的時(shí)候,如果這個(gè)類還有其他開(kāi)發(fā)者,你將不能保證這個(gè)方法真的會(huì)在事務(wù)環(huán)境中 3:再換句話說(shuō),Spring的事務(wù)傳播策略在內(nèi)部方法調(diào)用時(shí)將不起作用。

不管你希望某個(gè)方法需要單獨(dú)事務(wù),是RequiresNew,還是要嵌套事務(wù),要Nested,等等,統(tǒng)統(tǒng)不起作用。
4:不僅僅是事務(wù)通知,所有你自己利用Spring實(shí)現(xiàn)的AOP通知,都會(huì)受到同樣限制。。。。

[解難]

問(wèn)題的原因已經(jīng)找到,其實(shí),我理想中的AOP實(shí)現(xiàn),應(yīng)該是下面這樣:

spring中@Transactional 無(wú)效如何解決

看完上述內(nèi)容,你們對(duì)spring中@Transactional 無(wú)效如何解決有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI