单一架构中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 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>