簡書日更 第10篇: Spring事務(wù)失效問題及解決方法
我們常用的是spring聲明式事務(wù)棚亩,即使用@Transactional注解 來對(duì)需要事務(wù)的方法進(jìn)行標(biāo)注鞋喇,在一定的情景下狸棍,會(huì)出現(xiàn)事務(wù)失效的問題伏嗜,
這也是一個(gè)經(jīng)常被問到的面試題粒蜈,今天來解析一下。
若只想看 Spring事務(wù)失效問題的解決方法 請(qǐng)?zhí)^前面2個(gè)小主題
1.Spring支持兩種類型的事務(wù)管理
編程式事務(wù)管理:我們需要手動(dòng)的對(duì)事務(wù)進(jìn)行提交和回滾罐脊,需要一定的代碼量和復(fù)雜度定嗓。
聲明式事務(wù)管理:業(yè)務(wù)代碼和事務(wù)管理分離,你只需用注解和XML配置來管理事務(wù)(SpringBoot中只需要使用注解即可)萍桌。
2.Spring事務(wù)的實(shí)現(xiàn)方式和實(shí)現(xiàn)原理
Spring事務(wù)的本質(zhì)其實(shí)就是數(shù)據(jù)庫對(duì)事務(wù)的支持宵溅,沒有數(shù)據(jù)庫的事務(wù)支持,spring是無法提供事務(wù)功能的上炎。
真正的數(shù)據(jù)庫層的事務(wù)提交和回滾是通過binlog或者redo log實(shí)現(xiàn)的层玲。
3.Spring事務(wù)失效的幾種可能
3.1 Spring因 傳播行為失效
spring是可能會(huì)因?yàn)閭鞑バ袨槎У模?dāng)我們?cè)赗UD的時(shí)候反症,可能會(huì)對(duì)其中的多個(gè)方法進(jìn)行事務(wù)辛块,但對(duì)事務(wù)的傳播行為限制有所不同,
又因?yàn)閟pring的聲明式事務(wù)是基于AOP的铅碍,當(dāng)不同的方法在同一個(gè)類中的時(shí)候润绵,如果直接調(diào)用,則無法讓AOP生效胞谈,則會(huì)導(dǎo)致被調(diào)用的方法
傳播行為失效尘盼。
解決辦法為:使用注入的方式,調(diào)用其方法烦绳。
3.2 Spring因 rollbackFor 失效
@Transactional的寫法
開始@Transactional如果只這樣寫卿捎,
那,當(dāng)投擲一個(gè)此類RuntimeException子類實(shí)例的實(shí)例時(shí)径密。(Errors也一樣-交替地-標(biāo)識(shí)事務(wù)回滾午阵。)從事務(wù)方法中拋出的已檢查異常將不被標(biāo)識(shí)進(jìn)行事務(wù)回滾。
讓checked例外也回滾:在整個(gè)方法前加上@Transactional(rollbackFor = Exception.class)
讓unchecked例外不回滾:@Transactional(notRollbackFor = RunTimeException.class)
不需要事務(wù)管理的(只查詢的)方法:@Transactional(傳播=傳播。NOT_SUPPORTED)
注意:如果異常被try {} catch {}扔掉底桂,事務(wù)就不回滾了植袍,如果想讓事務(wù)回滾必須再往外拋try {} catch {throw Exception}。
注意:
Spring團(tuán)隊(duì)的建議是你在具體的類(或類的方法)上使用@Transactional注解籽懦,而不要使用在類所要實(shí)現(xiàn)的任何接口上于个。你當(dāng)然可以在接口上使用@Transactional注解,但是這將只能因?yàn)樽⒔馐遣荒芾^承的暮顺,這意味著如果您正在使用基于類的代理時(shí)厅篓,那么事務(wù)的設(shè)置將不能被基于類的代理所識(shí)別,而且對(duì)象也將不會(huì)被事務(wù)代理所包裝(將被確認(rèn)為嚴(yán)重的)捶码。因此贷笛,請(qǐng)接受Spring團(tuán)隊(duì)的建議和在具體的類上使用@Transactional注解。
@Transactional注解標(biāo)識(shí)的方法宙项,處理過程正確 的簡單乏苦。尤其是帶鎖的事務(wù)方法,能不放在事務(wù)里面的最好不要放在事務(wù)里面尤筐』慵觯可以將常規(guī)的數(shù)據(jù)庫查詢操作放在事務(wù)前面進(jìn)行,而事務(wù)內(nèi)部進(jìn)行增值盆繁,刪除掀淘,改,加鎖查詢等操作油昂。