单一架构中Spring手动或自动抛出异常时,既要要返回错误信息,还要做事务回滚
情况一:代码出现异常
@Override
@Transactional(rollbackFor = Exception.class)
public RspMessage add() {
Inventory inventory = new Inventory();
inventory.setGoodsId(2);
inventory.setGoodsNumber(11);
inventory.setCreateTime(new Date());
inventory.setStatus(0);
inventoryDao.insert(inventory);//新增数据
String st = "adafasd";
Integer.parseInt(st);//这里会出现异常
return new RspSuccessMessage();
}
出现异常时,这里会对新增数据时,进行异常回滚,但是如果没有做全局异常捕获,这里是会返回异常,不会返回自定义的错误码的。
情况二:代码出现异常
@Override
@Transactional(rollbackFor = Exception.class)
public RspMessage add() {
try{
Inventory inventory = new Inventory();
inventory.setGoodsId(2);
inventory.setGoodsNumber(11);
inventory.setCreateTime(new Date());
inventory.setStatus(0);
inventoryDao.insert(inventory);//新增数据
String st = "adafasd";
Integer.parseInt(st);//这里会报异常
}catch (Exception e){
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚事务
return new RspFailMessage("","保存错误:"+e.getMessage());//自定义的返回信息
}
return new RspSuccessMessage();
}
如果这里不加上:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚事务
那么这里捕获了异常,事务也不会回滚的。
(建议使用)情况三:手动抛出异常,假如:一个方法需要对3个数据表进行修改,但是其中前面的2个表修改成功了,但是第3个表失败了,那么这里就要手动抛出事务,对前面2个表就行事务回滚。
@Override
@Transactional(rollbackFor = Exception.class)
public RspMessage add() {
try{
Inventory inventory = new Inventory();
inventory.setGoodsId(3);
inventory.setGoodsNumber(11);
inventory.setCreateTime(new Date());
inventory.setStatus(0);
int i = inventoryDao.insert(inventory);
if (i == 0){
//这里是我自定义的异常,专门用来判断是否满足业务条件的,
// 比如:有两个保存,第一个新增执行完成了,但是第二个新增没有保存成功,但是也没有报异常,这个时候,就需要手动抛出异常,让第一个新增回滚
throw new DissatisfyConditionException("保存失败");//手动抛出异常
}
}catch (Exception e){
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚事务
return new RspFailMessage("","保存错误:"+e.getMessage());//返回自定义的信息
}
return new RspSuccessMessage();
}
上面的情况二、情况三;都是使用的 try catch 捕获异常,如果是捕获异常,必须要要加上哪一串代码的,才可以进行事务回滚,如果使用抛出异常,那么必须要写一个全局的异常捕获来处理异常了,不然使用抛出异常,是返回不了自定义的信息的。
自定义异常:
/**
* 自定义异常,用于抛出 业务中不满足继续执行下去的条件的异常
*/
public class DissatisfyConditionException extends Exception {
// 提供一个有参数的构造方法,可自动生成
public DissatisfyConditionException(String message) {
super(message);// 把参数传递给Throwable的带String参数的构造方法
}
}
spring boot的全局异常捕获:
import com.qw.utils.RspFailMessage;
import com.qw.utils.RspMessage;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolationException;
import java.util.Map;
import static java.util.stream.Collectors.toMap;
/**
* 全局异常捕获
*/
@RestControllerAdvice
public class GlobalExceptionHandle {
/**
* 用于 Spring validation后台校验框架 中实体类的注解验证的错误
* @param e
* @return
*/
@ExceptionHandler(value = BindException.class)//value : 需要捕获的异常,可以填写多个。
public RspMessage modelFieldEmptyException(BindException e) {
Map<String, Object> errors = e.getBindingResult().getFieldErrors().stream().collect(toMap(FieldError::getField, FieldError::getDefaultMessage));
return new RspFailMessage(errors);//返回的自定义信息
}
/**
* 捕获自定义的异常,这个异常是业务层中不满足条件的异常。
* @param e
* @return
*/
@ExceptionHandler(value = DissatisfyConditionException.class)
public RspFailMessage modelFieldEmptyException(DissatisfyConditionException e) {
return new RspFailMessage(e.getMessage());//返回的自定义信息
}
}
版权声明:本文为java_xuetu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。