异常: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。