關(guān)于Spring中@Transactional事務(wù)回滾的注意事項
一、Spring 默認(rèn)事務(wù)
Spring中 @Transactional
注解,默認(rèn)情況下,只對拋出的 RuntimeException
異常,才會事務(wù)回滾。
如果事務(wù)的方法中拋出 unchecked異常(RuntimeException),事務(wù)會進(jìn)行回滾( rollback);如果事務(wù)的方法中拋出是 checked異常(Exception),事務(wù)不會回滾。
也就是說,默認(rèn)情況下, @Transactional
注解 只對拋出的 RuntimeException
異常和其子類異常 才有效,對 Exception 及 Exception 的子類異常無效。
偽代碼說明
// @Transactional 默認(rèn)就是 RuntimeException 有效,拋出 RuntimeException時,事務(wù)會回滾。 @Transactional public void methodName1() { //... 各種的業(yè)務(wù)邏輯省略 throw new RuntimeException("RuntimeException"); } // @Transactional 默認(rèn)就是 RuntimeException 有效,拋出 Exception 時,事務(wù)不會回滾。 @Transactional public void methodName22() { //... 各種的業(yè)務(wù)邏輯省略 throw new Exception("Exception"); } // @Transactional 指定回滾事務(wù)是 Exception時,遇到 RuntimeException 時,事務(wù)不會回滾 @Transactional( rollbackFor=Exception.class ) public void methodName3() { //... 各種的業(yè)務(wù)邏輯省略 throw new RuntimeException("RuntimeException"); } // @Transactional 指定回滾事務(wù)是 Exception時,遇到異常 Exception 時,事務(wù)會回滾, @Transactional( rollbackFor=Exception.class ) public void methodName4() { //... 各種的業(yè)務(wù)邏輯省略 throw new Exception("Exception"); }
@Transactional
相當(dāng)于 @Transactional(rollbackFor=RuntimeException.class)
,只對拋出的 RuntimeException
異常,才會事務(wù)回滾。
1.1、拋出 unchecked 和 checked 異常都回滾
如果希望無論拋出是 RuntimeException (unchecked ) ,還是 Exception (checked),事務(wù)都要回滾。
@Transactional( rollbackFor = {RuntimeException.class, Exception.class} ) public void methodName5() { //... 業(yè)務(wù)省略 if(){ throw new RuntimeException("RuntimeException"); } //... 業(yè)務(wù)省略 if(){ throw new Exception("Exception"); } }
1.2、總結(jié)
- Spring 中
@Transactional
,默認(rèn)只對拋出的RuntimeException
的出常,事務(wù)才會回滾。 - 如果希望無論拋出是 RuntimeException ,還是 Exception,事務(wù)都要回滾,請使用如下配置。
@Transactional(rollbackFor={RuntimeException.class, Exception.class})
二、使用 Spring中 @Transactional 注解的注意事項
@Transactional
注解只能應(yīng)用到public
的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會報錯, 但是這個被注解的方法將不會展示已配置的事務(wù)設(shè)置。- 配置
proxy-target-class
是指定基于接口的,還是基于類的代理被創(chuàng)建。如果proxy-target-class
=false
(默認(rèn)值),那么標(biāo)準(zhǔn)的JDK基于接口的代理。 如果proxy-target-class
=true
,那么基于類的代理將起作用(需要CGLIB庫)。 @Transactional
注解 加在 具體方法(或類)上面 ,而不是接口上面。 在接口上使用 @Transactional 注解,只能當(dāng)你設(shè)置了基于接口的代理時它才生效。 因為注解是 不能繼承 的,這就意味著如果正在使用基于類的代理時,那么事務(wù)的設(shè)置將不能被基于類的代理所識別,而且對象也將不會被事務(wù)代理所包裝。@Transactional
的事務(wù)是通過基于接口的,或者是基于類的代理才能被創(chuàng)建。在同一個類中一個方法調(diào)用另一個有事務(wù)注解的方法,事務(wù)是不會起作用的。
這條能理解嗎 ?下面是解釋說明。
偽代碼說明
@Serive public class XxxService{ public void aa(){ //業(yè)務(wù)... bb() //業(yè)務(wù)... } @Transactional public void bb(){ //業(yè)務(wù)... } } @Controller public class XxxController(){ @Autowired XxxService xxxService; @RquestMapping("/hello") public void hello(){ xxxService.aa(); } } XxxController.hello() 調(diào)用 XxxService 時,沒有開啟事務(wù),在 aa()、 bb()發(fā)生的RuntimerException 不會事務(wù)回滾。 分析說明: (1)因為 aa() 沒有 @Transactional 注解,因此 XxxController 調(diào)用 XxxService 時 ,沒有開啟事務(wù); (2)aa()中調(diào)有 bb() 只是方法的調(diào)用(代碼片段的調(diào)用)。類似于Thread中,開啟線程是通過start()方法,而不是直接調(diào)用run()方法。
spring 在掃描bean的時候會掃描方法上是否包含@Transactional
事務(wù)注解,如果包含,則 spring會為這個bean動態(tài)地生成一個子類(即代理類,proxy),代理類是繼承原來那個bean 。
當(dāng)這個有事務(wù)注解的方法被調(diào)用的時候,實際上是由代理類來調(diào)用的,代理類在調(diào)用之前就會開啟事務(wù)(transaction
) 。
但是,如果先調(diào)用一個沒有事務(wù)的方法,然通這個方法再去有事務(wù),由于該方法的調(diào)用并沒有通過代理類,而是直接通過原來的那個bean,所以就不會啟動transaction,我們看到的現(xiàn)象就是 @Transactional
注解無效。
總結(jié): 同一個類中,一個沒有事務(wù)的方法A,去調(diào)用另一個有事務(wù)的方法B時,因為是直接調(diào)用,而不是調(diào)用的代理類,所以事務(wù)不起用的。
到此這篇關(guān)于關(guān)于Spring中@Transactional事務(wù)回滾的注意事項的文章就介紹到這了,更多相關(guān)Spring中@Transactional事務(wù)回滾內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java SMM框架關(guān)聯(lián)關(guān)系映射示例講解
SSM框架是spring MVC ,spring和mybatis框架的整合,是標(biāo)準(zhǔn)的MVC模式,將整個系統(tǒng)劃分為表現(xiàn)層,controller層,service層,DAO層四層,使用spring MVC負(fù)責(zé)請求的轉(zhuǎn)發(fā)和視圖管理,spring實現(xiàn)業(yè)務(wù)對象管理,mybatis作為數(shù)據(jù)對象的持久化引擎2022-08-08簡單了解SpringMVC緩存對靜態(tài)資源有什么影響
這篇文章主要介紹了簡單了解SpringMVC緩存對靜態(tài)資源有什么影響,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09java實現(xiàn)頁面多查詢條件必選的統(tǒng)一處理思路
這篇文章主要為大家介紹了java實現(xiàn)頁面多查詢條件必選的統(tǒng)一處理思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06SpringBoot整合redis+Aop防止重復(fù)提交的實現(xiàn)
Spring Boot通過AOP可以實現(xiàn)防止表單重復(fù)提交,本文主要介紹了SpringBoot整合redis+Aop防止重復(fù)提交的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07