您好,登錄后才能下訂單哦!
這篇文章主要介紹了controller的異常處理及service層的事務(wù)控制方法的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇controller的異常處理及service層的事務(wù)控制方法文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。
最近寫代碼涉及到一些事務(wù),上午終于把代碼給理順了,之前不太清楚在哪里做異常處理,導(dǎo)致代碼遍地try-catch,相當(dāng)難看。
還是基于controller-service-dao三層來(lái)寫代碼,從入口開(kāi)始,controller層的方法對(duì)應(yīng)的是某個(gè)url,面向的是應(yīng)用人員,應(yīng)該返回他們能讀懂的信息,所以controller必須做異常處理,一般來(lái)說(shuō)會(huì)有統(tǒng)一的異常處理方法;
service層面向的是controller,service層中的某些方法,必須保證其事務(wù),所以在service層進(jìn)行事務(wù)控制是相當(dāng)必要的,對(duì)于多條sql進(jìn)行事務(wù)控制,如果某個(gè)sql執(zhí)行失敗,那么應(yīng)當(dāng)對(duì)已經(jīng)執(zhí)行的sql語(yǔ)句進(jìn)行回滾;
dao層更多是單一的sql語(yǔ)句,沒(méi)有必要進(jìn)行事務(wù)控制,因?yàn)槭聞?wù)開(kāi)銷并不便宜(官方原話);
基于以上三點(diǎn),回頭再思考關(guān)于異常的處理,一般情況應(yīng)該把異常網(wǎng)上拋,一直拋到最終處理的那一層,所以對(duì)于dao層和service其實(shí)是沒(méi)有必要進(jìn)行try-catch的,直接往上拋異常就可以。
與之對(duì)應(yīng)的,是spring的事務(wù)配置,默認(rèn)情況下,spring只對(duì)運(yùn)行時(shí)異常進(jìn)行回滾,如果在dao層處理了異常,那么需要進(jìn)行額外的配置,spring才會(huì)對(duì)異常進(jìn)行回滾,常用的配置是@Transactional(rollbackFor=Exception.class)
順便提一個(gè)java知識(shí)點(diǎn),關(guān)于try-catch-finally中,finally的作用,finally設(shè)計(jì)之初就是為了關(guān)閉資源,如果在finally中使用return語(yǔ)句,會(huì)覆蓋try或者catch的返回值,最常見(jiàn)的就是覆蓋異常,即便catch往上拋了異常,也會(huì)被覆蓋,返回finally中return語(yǔ)句的返回值。
By default, a transaction will be rolling back on {@link RuntimeException}and {@link Error} but not on checked exceptions (business exceptions).
默認(rèn)情況下,如果在事務(wù)中拋出了未檢查異常(繼承自 RuntimeException 的異常)或者 Error,則 Spring 將回滾事務(wù);除此之外,Spring 不會(huì)回滾事務(wù)。
默認(rèn)spring事務(wù)只在發(fā)生未被捕獲的 RuntimeException 時(shí)才回滾。
// 測(cè)試回滾成功案例,基于IllegalArgumentException(RuntimeException)實(shí)現(xiàn)回滾 @GetMapping("/testSuccess") @Transactional// 如果不加,就不會(huì)回滾 public R testSuccess(@RequestParam("type") Integer type){ eduTeacherService.removeById("2"); if (type == 1){ throw new IllegalArgumentException("測(cè)試回滾成功案例!"); } eduTeacherService.removeById("3"); return R.ok(); }
Exception異常,事務(wù)回滾失?。?/p>
// 測(cè)試回滾失敗案例,基于Exception實(shí)現(xiàn)回滾; @GetMapping("/testFail") @Transactional public R testFail(@RequestParam("type") Integer type) { try { eduTeacherService.removeById("2"); if (type == 1){ throw new Exception("測(cè)試回滾失敗案例!"); } eduTeacherService.removeById("3"); } catch (Exception e) { e.printStackTrace(); } return R.ok(); }
用rollbackFor解決Exception不進(jìn)行事務(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("測(cè)試回滾失敗rollbackFor成功案例!"); } eduTeacherService.removeById("3"); return R.ok(); }
手動(dòng)回滾解決Exception不進(jìn)行事務(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("測(cè)試回滾失敗案例!"); } eduTeacherService.removeById("3"); } catch (Exception e) { e.printStackTrace(); //手動(dòng)回滾,如果sql2()拋了異常,sql1()會(huì)回滾,不影響事物正常執(zhí)行 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } return R.ok(); }
關(guān)于“controller的異常處理及service層的事務(wù)控制方法”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“controller的異常處理及service層的事務(wù)控制方法”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。