《从零开始的java从入门到入土的学习生活——JavaWeb后端篇》Chapter19——JavaWeb后端篇学习记录——Spring事务管理、异常处理

一、Spring事务管理

1、问题分析与解决

在实现的一些新增员工的功能中,一旦在保存员工基本信息后中间的部分出现异常。 导致员工信息保存成功,但是工作经历信息保存失败,造成了数据的不完整不一致。

为了保证操作前后,数据的一致性,就需要让新增员工中涉及到的两个业务操作,要么全部成功,要么全部失败 。可以通过事务来实现来保证这个功能。

2、Transactional注解

注解:@Transactional

**作用:**就是在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交事务。如果在这个方法执行的过程当中出现了异常,就会进行事务的回滚操作。

位置:

方法上:当前方法交给spring进行事务管理

类上:当前类中所有的方法都交由spring进行事务管理

接口上:接口下所有的实现类当中所有的方法都交给spring 进行事务管理

@Transactional注解:一般会在业务层当中来控制事务,因为在业务层当中,一个业务功能可能会包含多个数据访问的操作。在业务层来控制事务,就可以将多个数据访问操作控制在一个事务范围内。

application.yml配置文件中开启事务管理日志,这样就可以在控制看到和事务相关的日志信息了

XML 复制代码
#spring事务管理日志
logging: 
  level: 
    org.springframework.jdbc.support.JdbcTransactionManager: debug

3、事务进阶

对业务方法加上注解@Transactional

java 复制代码
@Transactional
@Override
public void save(Emp emp) {
    //1.补全基础属性
    emp.setCreateTime(LocalDateTime.now());
    emp.setUpdateTime(LocalDateTime.now());
    //2.保存员工基本信息
    empMapper.insert(emp);
        
    //模拟异常
    int i = 1/0;
        
    //3. 保存员工的工作经历信息 - 批量
    Integer empId = emp.getId();
    List<EmpExpr> exprList = emp.getExprList();
    if(!CollectionUtils.isEmpty(exprList)){
        exprList.forEach(empExpr -> empExpr.setEmpId(empId));
        empExprMapper.insertBatch(exprList);
    }
}

①rollbackFor

出现异常之后,如果我们在方法上加了@Transactional注解进行事务管理,所以发生异常会执行rollback回滚操作,从而保证事务操作前后数据是一致的。

默认情况下,RuntimeException(运行时异常)才会回滚事务。要让所有的异常都回滚,需要来配置@Transactional注解当中的rollbackFor属性,通过rollbackFor这个属性可以指定出现何种异常类型回滚事务。

java 复制代码
@Transactional(rollbackFor = Exception.class)

当我们启动服务后,在页面上进行相关业务操作时发生异常时,就会进行事务回滚

**总结:**在Spring的事务管理中,默认只有运行时异常 RuntimeException才会回滚。

如果还需要回滚指定类型的异常,可以通过rollbackFor属性来指定。

②propagation

propagation是用来配置事务的传播行为(当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制)的。

要想控制事务的传播行为,在@Transactional注解的后面指定一个属性propagation,通过 propagation 属性来指定传播行为。

常见的事务传播行为:

在一般的事务传播行为中,REQUIRED: 大部分情况下都是用该传播行为即可。**REQUIRES_NEW:**当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。

4、事务的四大特性(ACID)

|---------|-----------------------------------------------------------------------------------------|
| 原子性 | 事务是不可分割的最小单元,要么全部成功,要么全部失败。 |
| 一致性 | 事务完成时,必须使所有的数据都保持一致状态。(如果事务成功的完成,那么数据库的所有变化将生效。如果事务执行出现错误,那么数据库的所有变化将会被回滚(撤销),返回到原始状态。) |
| 隔离性 | 数据库系统提供的隔离机制(多个用户并发的访问数据库时,一个用户的事务不能被其他用户的事务干扰),保证事务在不受外部并发操作影响的独立环境下运行。 |
| 持久性 | 事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。 |

二、异常处理

1、问题分析

当我们的项目出现了异常后,服务端并不会做任何的处理:

Mapper接口在操作数据库的时候出错了,此时异常会往上抛(谁调用Mapper就抛给谁),会抛给service。service 中也存在异常了,会抛给controller。而在controller当中,我们也没有做任何的异常处理,所以最终异常会再往上抛。最终抛给框架之后,框架就会返回一个JSON格式的数据,里面封装的就是错误的信息。

2、全局异常处理器

定义一个异常处理类,并加上注解@ExceptionHandler
java 复制代码
/**
 * 全局异常处理器
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    //处理异常
    @ExceptionHandler
    public Result ex(Exception e){//方法形参中指定能够处理异常的异常类型
        e.printStackTrace();//打印异常信息
        //捕获到异常后,响应一个标准的Result
        return Result.error("对不起,操作失败,请联系管理员");

    }
}

记得在类前加上@RestControllerAdvice的注解,@RestControllerAdvice = @ControllerAdvice + @ResponseBody;处理异常的方法返回值会转换为json后再响应给前端

测试:

当我们启动项目后,输入一个数据已经存在的手机号后,发生异常:

出现异常之后,异常已经被全局异常处理器捕获了。然后返回的错误信息,被前端程序正常解析,然后提示出了对应的错误提示信息。

|---------------------------|-------------------|
| @RestControllerAdvice | 表示当前类为全局异常处理器 |
| @ExceptionHandler | 指定可以捕获哪种类型的异常进行处理 |

相关推荐
亚马逊云开发者1 小时前
article
java·开发语言
小陈phd1 小时前
多模态大模型学习笔记(二十五)—— 核心技术篇② | 虚拟人的大脑:国内头部大语言模型全解析
笔记·学习·语言模型
云烟成雨TD1 小时前
Spring AI 1.x 系列【11】基于 PromptTemplate 构建一站式 AI 写作助手
java·人工智能·spring
小旭95271 小时前
Spring 纯注解配置与 SpringBoot 入门详解
java·开发语言·spring boot·后端·spring
ADRU1 小时前
SSE 到底是什么?它和 HTTP 有什么关系?Java/Spring 怎么实现流式输出(可直接上手)
java·spring·http
de_wizard2 小时前
Spring Boot 整合 Keycloak
java·spring boot·后端
Re_zero2 小时前
throws 还是 try-catch?Code Review 里被我打回最多的异常处理
java·代码规范
VelinX2 小时前
【个人学习||算法】动态规划
学习·算法·动态规划
TON_G-T2 小时前
深入学习webpack-tapable
前端·学习·webpack