Springboot中@Transactional注解與異常處理機制方式
Springboot @Transactional注解與異常處理機制
@Transactional注解的方法默認(rèn)會捕獲所有非檢查異常,即RuntimeException和Error,可以通過括號聲明顯示指定處理異常類,如Exception.class
關(guān)于異常處理機制:
當(dāng)代碼拋出異常時,異常處理的優(yōu)先級如下:
- try-catch 塊:如果在代碼中使用了 try-catch 塊來捕獲異常,異常將會首先被 try-catch 塊捕獲并處理。只有在 try-catch 塊中未處理(重新拋出)異常時,異常才會繼續(xù)傳播。
- @Transactional:如果異常從 try-catch 塊中傳播出來,Spring 的事務(wù)管理器(由 @Transactional 注解管理)會捕獲異常并決定是否回滾事務(wù)。事務(wù)處理之后,異常繼續(xù)傳播。
- @ExceptionHandler:最后,異常會被全局異常處理器(由 @ControllerAdvice 和 @ExceptionHandler 注解管理)捕獲并處理。
因此,對于手動捕獲的異常,需要手動將其拋出才會被@Transactional處理器捕獲,全局處理器的優(yōu)先級最后,除了特殊的異??赡苄枰{(diào)整傳播順序,大部分不需要考慮其影響。
@Transactional錯誤集錦以及如何正確使用
原理
@Transactional 是聲明式事務(wù)管理 編程中使用的注解,通過Spring AOP在注解修飾方法的前后織入事務(wù)管理的實現(xiàn)語句,所以開發(fā)者只需要通過一個注解就能代替一系列繁瑣的事務(wù)開始、事務(wù)關(guān)閉等重復(fù)性的編碼任務(wù)。
添加位置
- 接口實現(xiàn)類或接口實現(xiàn)方法上,而不是接口類中。
- 訪問權(quán)限:public 的方法才起作用。@Transactional 注解應(yīng)該只被應(yīng)用到 public 方法上,這是由 Spring AOP 的本質(zhì)決定的。
- 系統(tǒng)設(shè)計:將標(biāo)簽放置在需要進行事務(wù)管理的方法上,而不是放在所有接口實現(xiàn)類上:只讀的接口就不需要事務(wù)管理,由于配置了@Transactional就需要AOP攔截及事務(wù)的處理,可能影響系統(tǒng)性能。
錯誤案例
1.同一個類中調(diào)用
public class A { public void methodA() { methodB(); // 其他操作 } @Transactional public void methodB() { // 寫數(shù)據(jù)庫操作 } }
上面案例是錯誤的基于Spring Aop的攔截機制,將會忽略事務(wù)。
解決方式如下:
@Service@AllArgsConstructorpublic class A { private B b; public void methodA() { b.methodB(); // 其他操作 }}@Servicepublic class B { @Transactional public void methodB() { // 寫數(shù)據(jù)庫操作 } }
注意:這里的B類沒有用@Autowrire,構(gòu)造函數(shù)用Lombok的@AllArgsConstructor生成 自動注入了。
2. @Transactional修飾方法不是public
public class TransactionalMistake { @Transactional private void method() { // 寫數(shù)據(jù)庫操作 } }
這也是基于Spring AOP實現(xiàn)的注解所要滿足的要求。這個最簡單, 直接把方法訪問類型改成public即可。
3. 不同的數(shù)據(jù)源
public class TransactionalMistake { @Transactional public void createOrder(Order order) { orderRepo1.save(order); orderRepo2.save(order); } }
上面這個例子里的orderRepo1和orderRepo2是連接的兩個不同數(shù)據(jù)源。
默認(rèn)情況下,這種跨數(shù)據(jù)源的事務(wù)是不會成功的。
如果要在多個數(shù)據(jù)源之間實現(xiàn)事務(wù),那么可以引入JTA。
4. 回滾異常配置不正確
默認(rèn)情況下,僅對RuntimeException和Error進行回滾。
如果不是的它們及它們的子孫異常的話,就不會回滾。
如果不是RuntimeException,但也希望觸發(fā)回滾,那么可以使用rollbackFor屬性來指定要回滾的異常。
public class TransactionalMistake { @Transactional(rollbackFor = XXXException.class) public void method() throws XXXException { } }
5. 數(shù)據(jù)庫引擎不支持事務(wù)
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
這里的spring.jpa.database-platform配置主要用來設(shè)置hibernate使用的方言。
這里特地采用了MySQL5InnoDBDialect,主要為了保障在使用Spring Data JPA時候,Hibernate自動創(chuàng)建表的時候使用InnoDB存儲引擎,不然就會以默認(rèn)存儲引擎MyISAM來建表,而MyISAM存儲引擎是沒有事務(wù)的。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring security實現(xiàn)下次自動登錄功能過程解析
這篇文章主要介紹了spring security實現(xiàn)記住我下次自動登錄功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11利用Java實體bean對象批量數(shù)據(jù)傳輸處理方案小結(jié)
javabean是對面向?qū)ο笏枷氲囊环N具體實施的表現(xiàn),本文重點給大家介紹利用Java實體bean對象批量數(shù)據(jù)傳輸處理方案小結(jié),本文通過兩種方案給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2021-05-05JSP 開發(fā)之hibernate的hql查詢多對多查詢
這篇文章主要介紹了JSP 開發(fā)之hibernate的hql查詢多對多查詢的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09IDEA利用自帶Axis工具和wsdl文件反向生成服務(wù)端客戶端代碼圖文詳解
這篇文章主要介紹了IDEA利用自帶Axis工具和wsdl文件反向生成服務(wù)端客戶端代碼詳細(xì)流程,在這里小編使用的是idea2021.1最新開發(fā)工具,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-05-05Java8深入學(xué)習(xí)系列(一)lambda表達式介紹
Java8最值得學(xué)習(xí)的特性就是Lambda表達式和Stream API,所以我們學(xué)習(xí)java8的第一課就是學(xué)習(xí)lambda表達式,下面這篇文章主要給大家介紹了關(guān)于Java8學(xué)習(xí)之lambda的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-08-08簡單了解Java synchronized關(guān)鍵字同步
這篇文章主要介紹了簡單了解Java synchronized關(guān)鍵字同步,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09Java使用JSONPath解析JSON完整內(nèi)容詳解
這篇文章主要介紹了Java使用JSONPath解析JSON完整內(nèi)容詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03