關(guān)于controller的異常處理及service層的事務(wù)控制方式
controller異常處理及service層的事務(wù)控制
最近寫代碼涉及到一些事務(wù),上午終于把代碼給理順了,之前不太清楚在哪里做異常處理,導(dǎo)致代碼遍地try-catch,相當難看。
還是基于controller-service-dao三層來寫代碼,從入口開始,controller層的方法對應(yīng)的是某個url,面向的是應(yīng)用人員,應(yīng)該返回他們能讀懂的信息,所以controller必須做異常處理,一般來說會有統(tǒng)一的異常處理方法;
service層面向的是controller,service層中的某些方法,必須保證其事務(wù),所以在service層進行事務(wù)控制是相當必要的,對于多條sql進行事務(wù)控制,如果某個sql執(zhí)行失敗,那么應(yīng)當對已經(jīng)執(zhí)行的sql語句進行回滾;
dao層更多是單一的sql語句,沒有必要進行事務(wù)控制,因為事務(wù)開銷并不便宜(官方原話);
基于以上三點,回頭再思考關(guān)于異常的處理,一般情況應(yīng)該把異常網(wǎng)上拋,一直拋到最終處理的那一層,所以對于dao層和service其實是沒有必要進行try-catch的,直接往上拋異常就可以。
與之對應(yīng)的,是spring的事務(wù)配置,默認情況下,spring只對運行時異常進行回滾,如果在dao層處理了異常,那么需要進行額外的配置,spring才會對異常進行回滾,常用的配置是@Transactional(rollbackFor=Exception.class)
順便提一個java知識點,關(guān)于try-catch-finally中,finally的作用,finally設(shè)計之初就是為了關(guān)閉資源,如果在finally中使用return語句,會覆蓋try或者catch的返回值,最常見的就是覆蓋異常,即便catch往上拋了異常,也會被覆蓋,返回finally中return語句的返回值。
controller層Exception異常事務(wù)回滾失效問題
Spring的@Transactional源碼中寫道
By default, a transaction will be rolling back on {@link RuntimeException}and {@link Error} but not on checked exceptions (business exceptions).
默認情況下,如果在事務(wù)中拋出了未檢查異常(繼承自 RuntimeException 的異常)或者 Error,則 Spring 將回滾事務(wù);除此之外,Spring 不會回滾事務(wù)。

測試①
默認spring事務(wù)只在發(fā)生未被捕獲的 RuntimeException 時才回滾。
// 測試回滾成功案例,基于IllegalArgumentException(RuntimeException)實現(xiàn)回滾
@GetMapping("/testSuccess")
@Transactional// 如果不加,就不會回滾
public R testSuccess(@RequestParam("type") Integer type){
eduTeacherService.removeById("2");
if (type == 1){
throw new IllegalArgumentException("測試回滾成功案例!");
}
eduTeacherService.removeById("3");
return R.ok();
}

測試②
Exception異常,事務(wù)回滾失??;
// 測試回滾失敗案例,基于Exception實現(xiàn)回滾;
@GetMapping("/testFail")
@Transactional
public R testFail(@RequestParam("type") Integer type) {
try {
eduTeacherService.removeById("2");
if (type == 1){
throw new Exception("測試回滾失敗案例!");
}
eduTeacherService.removeById("3");
} catch (Exception e) {
e.printStackTrace();
}
return R.ok();
}

測試③
用rollbackFor解決Exception不進行事務(wù)回滾
rollbackFor = Exception.class + throws Exception
@GetMapping("/testFailRollbackFor")
// 配置rollbackFor
@Transactional(propagation= Propagation.REQUIRED,rollbackFor = Exception.class)
public R testFailRollbackFor(@RequestParam("type") Integer type) throws Exception {
eduTeacherService.removeById("2");
if (type == 1){
throw new Exception("測試回滾失敗rollbackFor成功案例!");
}
eduTeacherService.removeById("3");
return R.ok();
}

測試④
手動回滾解決Exception不進行事務(wù)回滾
catch: TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@GetMapping("/testSuccessByHand")
@Transactional
public R testSuccessByHand(@RequestParam("type") Integer type) {
try {
eduTeacherService.removeById("2");
if (type == 1){
throw new Exception("測試回滾失敗案例!");
}
eduTeacherService.removeById("3");
} catch (Exception e) {
e.printStackTrace();
//手動回滾,如果sql2()拋了異常,sql1()會回滾,不影響事物正常執(zhí)行
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return R.ok();
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java門禁系統(tǒng)面向?qū)ο蟪绦蛟O(shè)計
這篇文章主要為大家詳細介紹了java門禁系統(tǒng)面向?qū)ο蟪绦蛟O(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01
SpringBoot4.5.2 整合HikariCP 數(shù)據(jù)庫連接池操作
這篇文章主要介紹了SpringBoot4.5.2 整合HikariCP 數(shù)據(jù)庫連接池操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
在Java中將double轉(zhuǎn)換為int的操作方法
這篇文章主要介紹了在Java中將double轉(zhuǎn)換為int的操作方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
java設(shè)置session過期時間的實現(xiàn)方法
這篇文章主要介紹了java設(shè)置session過期時間的實現(xiàn)方法,以實例形式詳細講述了具體實現(xiàn)過程,非常具有參考借鑒價值,需要的朋友可以參考下2014-10-10
海量數(shù)據(jù)去重排序bitmap(位圖法)在java中實現(xiàn)的兩種方法
今天小編就為大家分享一篇關(guān)于海量數(shù)據(jù)去重排序bitmap(位圖法)在java中實現(xiàn)的兩種方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02

