前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记录一次Spring事务线上异常

记录一次Spring事务线上异常

作者头像
JavaEdge
发布2023-01-11 11:29:12
5010
发布2023-01-11 11:29:12
举报
文章被收录于专栏:JavaEdgeJavaEdge

Spring事务管理配置方式:

  • XML模糊匹配,绑定事务管理
  • 注解,可对每个需要进行事务处理的方法单独配置,只需 @Transactional,然后添加属性配置

为简便,本文使用注解方式。Spring初始化时,会通过扫描拦截对事务的方法进行增强。若目标方法存在事务,Spring就会创建一个Bean对应的代理(Proxy)对象,并进行相关的事务处理操作。

1 setup

1.1 数据库配置文件 jdbc.properties

1.2 JDBC配置类

从 jdbc.properties 加载相关配置项,并创建 JdbcTemplate、DataSource、TransactionManager 等相关Bean。

1.3 应用配置类

通过注解,配置了数据源、MyBatis Mapper 的扫描路径以及事务等。

2 unchecked 异常与事务回滚

用户管理功能,每位用户注册后,都往数据库里存入信息:

Mapper类:

数据库表Schema:

业务类 StudentService包括一个保存的方法 saveStudent。执行一下保存,一切正常。

测试该事务是否回滚:若发现用户名=JavaEdge,抛异常,触发事务回滚。

测试保存我这个用户:

执行结果打印出了这样的信息:

异常抛了,但观察到DB还是有条新记录。

那为何异常也抛了,却没有回滚?

3 源码解析

顺着 saveUser debug:

看到 CglibAopProxy,事务本质上也是一种特殊切面,在创建过程中,被 CglibAopProxy 代理。 事务处理拦截器是 TransactionInterceptor支撑整个事务功能的架构

TransactionInterceptor如何实现事务特性

执行代理类的目标方法时,触发invoke()。跳到异常处理。catch到异常时,调 completeTransactionAfterThrowing进一步处理。

TransactionAspectSupport#invokeWithinTransaction

completeTransactionAfterThrowing.rollbackOn()

事务回滚判断条件。条件满足时,即会触发事务回滚。

RuleBasedTransactionAttribute#rollbackOn()

RuleBasedTransactionAttribute自身的rollbackOn()

当在 @Transactional 配置 rollbackFor,该方法就会用捕获到的异常和 rollbackFor 中配置的异常比对:

  • 所捕获异常是 rollbackFor 配置异常,直接 rollback

案例中,没有加任何规则,所以找不到规则去处理(所以 winner == null),进而走到下一步。

DefaultTransactionAttribute 的 rollbackOn()

当发生如下 case:

  • 没有在 @Transactional 配置 rollback 属性
  • 或者,捕获到的异常和所配置异常类型不一

就调用父类rollbackOn():

只有异常类型为 RuntimeException 或 Error,才true =》才触发 completeTransactionAfterThrowing#rollback =》事务才回滚:

综上,Spring 处理事务时,若没有在 @Transactional 配置 rollback 属性,则只有捕获到 RuntimeException 或 Error 才会触发事务回滚。 而案例抛 Exception,又未指定回滚规则,所以未触发回滚。

4 修正

将所抛异常类型改成 RuntimeException:

这种修改方法不优雅,毕竟异常有时就是固定死不能修改。还有更好方案。

解析 RuleBasedTransactionAttribute#rollbackOn 的代码时提到过 rollbackFor 属性的处理规则。在 @Transactional 的 rollbackFor 加入要支持的异常类型(在这是 Exception)即可匹配上我们所抛异常。完善注解配置即可:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-01-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 setup
    • 1.1 数据库配置文件 jdbc.properties
      • 1.2 JDBC配置类
        • 1.3 应用配置类
        • 2 unchecked 异常与事务回滚
        • 3 源码解析
          • TransactionInterceptor如何实现事务特性
            • TransactionAspectSupport#invokeWithinTransaction
              • completeTransactionAfterThrowing.rollbackOn()
            • RuleBasedTransactionAttribute#rollbackOn()
              • RuleBasedTransactionAttribute自身的rollbackOn()
              • DefaultTransactionAttribute 的 rollbackOn()
          • 4 修正
          相关产品与服务
          数据库
          云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档