解析spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class
spring中事務(wù)處理原理
利用aop生成代理對象執(zhí)行帶有Transactional事務(wù)注解的方法業(yè)務(wù)邏輯.項目啟動過程中會生成代理對象并將Transactional注解中的屬性進行解析加載處理.在方法執(zhí)行過程中如果出現(xiàn)異常,會根據(jù)注解配置決定是進入到事務(wù)回滾處理還是事務(wù)提交處理邏輯中,事務(wù)回滾處理邏輯中最終還是基于數(shù)據(jù)庫的事務(wù)回滾處理.
異常的分類
案例說明
以自定義異常為例說明一下@Transactional中是否指定rollbackFor=Exception.class的區(qū)別
未指定rollbackFor屬性
@Transactional @GetMapping("/addSysMenu") public void addSysMenu() throws Exception { // 更新菜單名稱(將id為1的菜單名修改為系統(tǒng)管理測試) int k = sysMenuDao.updateSysMenu(1, "系統(tǒng)管理測試"); System.out.println(k); // 自定義異常,拋出非運行期異常 throw new Exception("自定義異常"); // 執(zhí)行結(jié)果:程序終止,數(shù)據(jù)庫中菜單id為1的菜單名修改成功.說明事物沒有回滾. }
指定rollbackFor屬性
@Transactional(rollbackFor = Exception.class) @GetMapping("/addSysMenu") public void addSysMenu(String menuName) throws Exception { // 更新菜單名稱(將id為1的菜單名修改為系統(tǒng)管理測試) int k = sysMenuDao.updateSysMenu(1, "系統(tǒng)管理測試"); System.out.println(k); // 自定義異常,拋出非運行期異常 throw new Exception("自定義異常"); // 執(zhí)行結(jié)果:程序終止,數(shù)據(jù)庫中菜單id為1的菜單名沒有修改.說明事物回滾. }
原因分析
其他帖子都說如果不加的話僅支持運行期異常以及error錯誤類型.對于非運行期異常是不支持的.這里提供一下這種說法的來源.
先看一下@Transactional注解中關(guān)于rollbackFor的使用說明
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional { // 省略部分代碼............ // By default, a transaction will be rolling back on {@link RuntimeException} and {@link Error} but not on checked exceptions (business exceptions). // 翻譯:指定事物回滾的異常類型,默認(rèn)僅對于運行期異常和錯誤支持事務(wù)回滾,對于檢查異常(業(yè)務(wù)異常是不支持的) Class<? extends Throwable>[] rollbackFor() default {}; }
至于加上@Transactional中指定rollbackFor=Exception.class以后是如何起作用的接著往下看.
spring中事務(wù)回滾的大概邏輯是,發(fā)生異常之后,會根據(jù)配置的事務(wù)屬性判斷是否進行回滾的處理,如果不進行事務(wù)回滾則直接進行事務(wù)提交.這里重要的體現(xiàn)是在:TransactionAspectSupport.java中completeTransactionAfterThrowing
// 發(fā)生異常時事務(wù)處理方式 protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.getTransactionStatus() != null) { // 省略部分代碼....... // 判斷異常是否為運行期異?;蚴莈rror,如果是則執(zhí)行回滾處理,如果不是則提交事務(wù) if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) { // 回滾事務(wù)處理 txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); // 省略部分代碼...... } else { // 提交事務(wù) txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); // 省略部分代碼....... } } }
而判斷事務(wù)是否支持回滾的處理在RuleBasedTransactionAttribute.java中transactionAttribute.rollbackOn()
// 判斷異常是否支持事務(wù)回滾處理 public boolean rollbackOn(Throwable ex) { RollbackRuleAttribute winner = null; // 省略部分代碼.................... // winner 是判斷@Transactional中是否有rollBackFor屬性,如果沒有則說明沒有指定,按照默認(rèn)的方式進行判斷(DefaultTransactionAttribute.java中rollbackOn),如果有則只判斷是否屬于NoRollbackRuleAttribute類型,如果不是則說明支持事務(wù)回滾.關(guān)于變量win對應(yīng)的RollbackRuleAttribute如何進行的賦值下面繼續(xù). if (winner == null) { return super.rollbackOn(ex); } return !(winner instanceof NoRollbackRuleAttribute); }
DefaultTransactionAttribute.java中rollbackOn,是否支持事務(wù)回滾的默認(rèn)判斷方式:是否是運行期異常或是是否是錯誤類型(與Transactional注解中的rollbackFor屬性說明相對應(yīng)).
public boolean rollbackOn(Throwable ex) { return (ex instanceof RuntimeException || ex instanceof Error); }
RollbackRuleAttribute中如何進行的賦值問題,具體來講是項目啟動之后會掃描帶有Transactional注解的方法,然后將注解中標(biāo)注的屬性獲取之后進行參數(shù)配置.具體體現(xiàn)是在:SpringTransactionAnnotationParser.java中parseTransactionAnnotation
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); // 省略部分代碼......... // 獲取注解上的rollbackFor屬性值 List<RollbackRuleAttribute> rollbackRules = new ArrayList<>(); for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) { rollbackRules.add(new RollbackRuleAttribute(rbRule)); } // 省略部分代碼......... return rbta; }
至此關(guān)于為什么@Transactional為什么要添加rollbackFor=Exception.class原因以講述完畢!
到此這篇關(guān)于spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class的文章就介紹到這了,更多相關(guān)spring事務(wù)管理@Transactional內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring中BeanUtils.copyProperties的坑及解決
這篇文章主要介紹了Spring中BeanUtils.copyProperties的坑及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09Spring security權(quán)限配置與使用大全
Spring Security 本質(zhì)上是借助一系列的 Servlet Filter來提供各種安全性功能,但這并不需要我們手動去添加或者創(chuàng)建多個Filter,本文重點給大家介紹spring-security的配置與使用及實現(xiàn)方式,感興趣的朋友一起看看吧2021-09-09JAVA大作業(yè)之圖書管理系統(tǒng)實現(xiàn)全解
隨著網(wǎng)絡(luò)技術(shù)的高速發(fā)展,計算機應(yīng)用的普及,利用計算機對圖書館的日常工作進行管理勢在必行,本篇文章手把手帶你用Java實現(xiàn)一個圖書管理系統(tǒng),大家可以在過程中查缺補漏,提升水平2022-01-01