面试官:你知道哪几种事务失效的场景?
前言
聲明式事務是Spring功能中最爽之一,可是有些時候,我們在使用聲明式事務并未生效,這是為什么呢?
今天陳某帶大家來聊一聊聲明事務的幾種失效場景。本文將會從以下兩個方面來說一下事務為什么會失效?
@Transactional介紹
@Transactional失效場景
這是我歷時三個月總結(jié)的?Java 面試 + Java 后端技術(shù)學習指南,本人這幾年及春招的總結(jié),目前,已經(jīng)拿到了大廠offer,拿去不謝!(目錄部分截圖)
下載方式
1.?首先掃描下方二維碼
2.?后臺回復「Java面試」即可獲取
@Transactional介紹
@Transactional是聲明式事務的注解,可以被標記在類上、接口、方法上。
該注解中有很多值得深入了解的幾種屬性,我們來看一下。
transactionManager
指定事務管理器,值為bean的名稱,這個主要用于多事務管理器情況下指定。比如多數(shù)據(jù)源配置的情況下。
isolation
事務的隔離級別,默認是Isolation.DEFAULT。
幾種值的含義如下:
Isolation.DEFAULT:事務默認的隔離級別,使用數(shù)據(jù)庫默認的隔離級別。
Isolation.READ_UNCOMMITTED:這是事務最低的隔離級別,它充許別外一個事務可以看到這個事務未提交的數(shù)據(jù)。這種隔離級別會產(chǎn)生臟讀,不可重復讀和幻讀。
Isolation.READ_COMMITTED:保證一個事務修改的數(shù)據(jù)提交后才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數(shù)據(jù)。這種事務隔離級別可以避免臟讀出現(xiàn),但是可能會出現(xiàn)不可重復讀和幻讀。
Isolation.REPEATABLE_READ:這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現(xiàn)幻讀。
Isolation.SERIALIZABLE:這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執(zhí)行。除了防止臟讀,不可重復讀外,還避免了幻讀。
propagation
代表事務的傳播行為,默認值為Propagation.REQUIRED。
Propagation.REQUIRED:如果存在一個事務,則支持當前事務。如果沒有事務則開啟一個新的事務。比如A方法內(nèi)部調(diào)用了B方法,此時B方法將會使用A方法的事務。
Propagation.MANDATORY:支持當前事務,如果當前沒有事務,就拋出異常。
Propagation.NEVER:以非事務方式執(zhí)行,如果當前存在事務,則拋出異常。
Propagation.NOT_SUPPORTED:以非事務方式執(zhí)行操作,如果當前存在事務,就把當前事務掛起。
Propagation.REQUIRES_NEW:新建事務,如果當前存在事務,把當前事務掛起。比如A方法使用默認的事務傳播屬性,B方法使用REQUIRES_NEW,此時A方法在內(nèi)部調(diào)用B方法,一旦A方法出現(xiàn)異常,A方法中的事務回滾了,但是B方法并沒有回滾,因為A和B方法使用的不是同一個事務,B方法新建了一個事務。
Propagation.NESTED:支持當前事務,新增Savepoint點,也就是在進入子事務之前,父事務建立一個回滾點,與當前事務同步提交或回滾。子事務是父事務的一部分,在父事務還未提交時,子事務一定沒有提交。嵌套事務一個非常重要的概念就是內(nèi)層事務依賴于外層事務。外層事務失敗時,會回滾內(nèi)層事務所做的動作。而內(nèi)層事務操作失敗并不會引起外層事務的回滾。
timeout
事務的超時時間,單位為秒。
readOnly
該屬性用于設(shè)置當前事務是否為只讀事務,設(shè)置為true表示只讀,false則表示可讀寫,默認值為false。如果一個事務只涉及到只讀,可以設(shè)置為true。
rollbackFor 屬性
用于指定能夠觸發(fā)事務回滾的異常類型,可以指定多個異常類型。
默認是在RuntimeException和Error上回滾。
noRollbackFor
拋出指定的異常類型,不回滾事務,也可以指定多個異常類型。
@Transactional失效場景
聲明式事務失效的場景有很多,陳某這里只是羅列一下幾種常見的場景。
底層數(shù)據(jù)庫引擎不支持事務
如果數(shù)據(jù)庫引擎不支持事務,則Spring自然無法支持事務。
在非public修飾的方法使用
@Transactional注解使用的是AOP,在使用動態(tài)代理的時候只能針對public方法進行代理,源碼依據(jù)在AbstractFallbackTransactionAttributeSource類中的computeTransactionAttribute方法中,如下:
此處如果不是標注在public修飾的方法上并不會拋出異常,但是會導致事務失效。
異常被 " 踹死了 "
這種情況小白是最容易犯錯的,在整個事務的方法中使用try-catch,導致異常無法拋出,自然會導致事務失效。偽代碼如下:
方法中調(diào)用同類的方法
簡單的說就是一個類中的A方法(未標注聲明式事務)在內(nèi)部調(diào)用了B方法(標注了聲明式事務),這樣會導致B方法中的事務失效。
代碼如下:
為什么會失效呢?:其實原因很簡單,Spring在掃描Bean的時候會自動為標注了@Transactional注解的類生成一個代理類(proxy),當有注解的方法被調(diào)用的時候,實際上是代理類調(diào)用的,代理類在調(diào)用之前會開啟事務,執(zhí)行事務的操作,但是同類中的方法互相調(diào)用,相當于this.B(),此時的B方法并非是代理類調(diào)用,而是直接通過原有的Bean直接調(diào)用,所以注解會失效。
如何解決呢?:這就涉及到注解失效的原因了,后續(xù)文章會介紹到,這里不過多介紹了。
rollbackFor屬性設(shè)置錯誤
很容易理解,指定異常觸發(fā)回滾,一旦設(shè)置錯誤,導致一些異常不能觸發(fā)回滾,此時的聲明式事務不就失效了嗎。
noRollbackFor屬性設(shè)置錯誤
這個和rollbackFor屬性設(shè)置錯誤類似,一旦設(shè)置錯誤,也會導致異常不能觸發(fā)回滾,此時的聲明式事務會失效。
propagation屬性設(shè)置錯誤
事務的傳播屬性在上面已經(jīng)介紹了,默認的事務傳播屬性是Propagation.REQUIRED,但是一旦配置了錯誤的傳播屬性,也是會導致事務失效,如下三種配置將會導致事務失效:
Propagation.SUPPORTS
Propagation.NOT_SUPPORTED
Propagation.NEVER
原始SSM項目,重復掃描導致事務失效
在原始的SSM項目中都配置了context:component-scan并且同時掃描了service層,此時事務將會失效。
按照Spring配置文件的加載順序來說,會先加載Springmvc的配置文件,如果在加載Springmvc配置文件的時候把service也加載了,但是此時事務還沒加載,將會導致事務無法成功生效。
解決方法很簡單,把掃描service層的配置設(shè)置在Spring配置文件或者其他配置文件中即可。
總結(jié)
事務失效的原因很多,但是千萬不要做到一知半解,只有深入理解了,才能在面試過程中對答如流。
今天的文章就到此結(jié)束了,如果覺得陳某寫得不錯,有所收獲的,關(guān)注在看來一波,你們的鼓勵,將會是我寫作的動力,謝謝支持!!!
最后,再附上我歷時三個月總結(jié)的?Java 面試 + Java 后端技術(shù)學習指南,這是本人這幾年及春招的總結(jié),目前,已經(jīng)拿到了大廠offer,拿去不謝!(目錄部分截圖)
下載方式
1.?首先掃描下方二維碼
2.?后臺回復「Java面試」即可獲取
總結(jié)
以上是生活随笔為你收集整理的面试官:你知道哪几种事务失效的场景?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Maven】maven 插件开发实战
- 下一篇: 为什么程序员都不喜欢使用switch,而