異常:Transaction rolled back because it has been marked as rollback-only
原因:已經標記為rollback-only,但是后面的程序執行后又commit事務,拋出此異常。雖然都回滾,不影響正常業務。但是日志打印這種異常讓人很難受。
解決辦法:(核心思想:既然標識為rollback-only,就不要讓事務再commit)
1.service不try catch。controller中try catch。異常會被層層感知,不會讓事務commit。
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public void addTest(){ testDao.addTest(); int i = 1/0; // try { // testDao.addTest(); // int i = 1/0; // return "success"; // }catch (Exception e){ // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // throw new RuntimeException(); // //return "exception"; // } }
2.service中try catch后,throw new RuntimeException();。讓調用方感知異常,不會讓事務commit。
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public String addTest(){ try { testDao.addTest(); int i = 1/0; return "success"; }catch (Exception e){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); throw new RuntimeException(); //return "exception"; } }
3.service中try catch后,手動回滾異常,並返回異常碼。外層判斷調用service結果,是否再手動回滾。雖然感知不到異常,但是通過判斷調用方返回結果,是否手動回滾。不會讓事務commit。
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public void addUser(){ try { userDao.addUser(); String logResult = logService.addLog(); if("exception".equals(logResult)){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return; } String testResult = testService.addTest(); if("exception".equals(testResult)){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return; } } catch (Exception e){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } System.out.println("end"); }
雖然報錯Transaction rolled back because it has been marked as rollback-only並不影響業務的正常邏輯。因為即使報這個異常,也會整體回滾。
但是為了解決這個問題。有一個核心思想就是:不要讓同一個事務標記為rollback-only后又commit。
以上三種方案都是防止事務標記為rollback-only后又commit。