1 訪問(wèn)權(quán)限問(wèn)題:
java的訪問(wèn)權(quán)限有4種:private、default、protected、public,它們的權(quán)限從左到右,以此變大。如果在開發(fā)中,將事務(wù)方法定義了錯(cuò)誤的訪問(wèn)權(quán)限,則事務(wù)功能會(huì)失效。這樣會(huì)導(dǎo)致事務(wù)失效,spring要求被代理方法必須是public的。、
在Spring源碼中,如果目標(biāo)方法不是public,則TransactionAttribute返回null,不支持事務(wù)。
2 方法用final修飾
放方法被final修飾時(shí),也會(huì)導(dǎo)致事務(wù)失效。
因?yàn)閟pring事務(wù)底層是用了aop,用了jdk的動(dòng)態(tài)代理或者cglb的動(dòng)態(tài)代理,會(huì)幫我們生成代理類,在代理類中實(shí)現(xiàn)事務(wù)功能。
如果某個(gè)方法被final修飾了,那么在代理類中,就無(wú)法重新該方法,而添加事務(wù)功能。
注意:如果某個(gè)方法被static修飾,同樣也無(wú)法通過(guò)動(dòng)態(tài)代理,變成事務(wù)方法。
3 直接調(diào)用內(nèi)部方法
由上可知:在事務(wù)方法add可知,它直接調(diào)用了updateStatus方法,
由2可知:方法擁有事務(wù)的能力是因?yàn)閟pring aop中生成了代理對(duì)象,但是直接調(diào)用updateStatus方法不會(huì)直接生成事務(wù)。
但是可以直接將該類直接注入進(jìn)來(lái),比如:
這樣事務(wù)就生效了,也不會(huì)穿生循環(huán)依賴的問(wèn)題。
4 未被Spring管理
5 多線程調(diào)用
? ? ? ? 由以下代碼可知:在add()事務(wù)方法里面,調(diào)用了updateStatus事務(wù)方法,但是updateStatus事務(wù)方法是在另外一個(gè)線程中調(diào)用的。這樣就導(dǎo)致了兩個(gè)方法不在同一個(gè)線程中,獲取到了數(shù)據(jù)庫(kù)連接不一樣,從而是兩個(gè)不同的事務(wù),如果updateStatus方法中拋出了異常,add方法是不會(huì)回滾的
? ? ? ? spring的事務(wù)是通過(guò)數(shù)據(jù)庫(kù)的連接來(lái)實(shí)現(xiàn)的。當(dāng)前線程中保存了一個(gè)map,key是數(shù)據(jù)源,value是數(shù)據(jù)庫(kù)連接。同一個(gè)事務(wù),指同一個(gè)數(shù)據(jù)庫(kù)連接,只有擁有同一個(gè)事務(wù)連接才能保證同時(shí)提交和回滾。如果是不同的線程,拿到的數(shù)據(jù)庫(kù)連接肯定是不同的。
6 表不支持事務(wù)
如果表的引擎是myisam,那么它是不支持事務(wù)的,要想支持事務(wù),改成innodb引擎
7 事務(wù)沒(méi)有開啟
如果是springBoot項(xiàng)目,那么是事務(wù)默認(rèn)是開啟的,但如果是spring項(xiàng)目,需要xml配置
8 事務(wù)的傳播特性
如果事務(wù)的傳播特性設(shè)置錯(cuò)了,事務(wù)也會(huì)失效。如下:propagation = Propagation.NEVER這種類型的傳播特性不支持事務(wù),如果有事務(wù)會(huì)拋出異常。
目前只有這三種傳播特性才會(huì)創(chuàng)建新事物:REQUIRED、REQUIRES_NEW、NESTED
9 自己吞了異常
事務(wù)不會(huì)回滾,最常見的問(wèn)題是:開發(fā)者在代碼中手動(dòng)try...catch了異常。如下:
這種情況下,因?yàn)殚_發(fā)者自己捕獲了異常、又沒(méi)有手動(dòng)拋出
10 手動(dòng)拋了別的異常
如果拋的異常不正確,事務(wù)也不會(huì)回滾
因?yàn)镾pring事務(wù),默認(rèn)情況下只會(huì)回滾RuntimeException(運(yùn)行時(shí)異常)和Error(錯(cuò)誤),對(duì)于普通的非運(yùn)行時(shí)異常,它不會(huì)回滾。
11 自定義回滾異常
如果在使用@Transactional注解聲明事務(wù)時(shí),有時(shí)想自定義回滾異常,spring也是支持的。可以通過(guò)設(shè)置rollbackFor參數(shù),來(lái)完成這個(gè)功能。如下:
但是如果在程序執(zhí)行過(guò)程中,出現(xiàn)了sql異常,但是sql異常并不屬于我們定義的BusinessException異常,所以事務(wù)也不會(huì)回滾