返回顶部
首页 > 资讯 > 后端开发 > Python >Spring @Transactional事务失效的原因分析
  • 710
分享到

Spring @Transactional事务失效的原因分析

2024-04-02 19:04:59 710人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录前言1.非 public 修饰的方法2.timeout 超时3.代码中有 try/catch4.调用类内部 @Transactional 方法5.数据库不支持事务总结前言 一个程

前言

一个程序中不可能没有事务,而 spring 中,事务的实现方式分为两种:编程式事务和声明式事务,又因为编程式事务实现相对麻烦,而声明式事务实现极其简单,所以在日常项目中,我们都会使用声明式事务 @Transactional 来实现事务。

@Transactional 使用极其简单,只需要在类上或方法上添加 @Transactional 关键字,就可以实现事务的自动开启、提交或回滚了,它的基础用法如下:

@Transactional 
@RequestMapping("/add")
public int add(UserInfo userInfo) {
    int result = userService.add(userInfo);
    return result;
}

@Transactional 执行流程

@Transactional 会在方法执行前,会自动开启事务;在方法成功执行完,会自动提交事务;如果方法在执行期间,出现了异常,那么它会自动回滚事务。

然而,就是看起来极其简单的 @Transactional,却隐藏着一些“坑”,这些坑就是我们今天要讲的主题:导致 @Transactional 事务失效的常见场景有哪些?

在开始之前,我们先要明确一个定义,什么叫做“失效”?

本文中的“失效”指的是“失去(它的)功效”,也就是当 @Transactional 不符合我们预期的结果时,我们就可以说 @Transactional 失效了。

那 @Transactional 失效的场景有哪些呢?接下来我们一一来看。

1.非 public 修饰的方法

当 @Transactional 修饰的方法为非 public 时,事务就失效了,比如以下代码当遇到异常之后,不能自动实现回滚:

@RequestMapping("/save")
int save(UserInfo userInfo) {
    // 非空效验
    if (userInfo == null ||
        !StringUtils.hasLength(userInfo.getUsername()) ||
        !StringUtils.hasLength(userInfo.getPassword()))
        return 0;
    // 执行添加操作
    int result = userService.save(userInfo);
    System.out.println("add 受影响的行数:" + result);
    int num = 10 / 0; // 此处设置一个异常
    return result;
}

以上程序的运行结果如下:

当程序出现运行时异常时,我们预期的结果是事务应该实现自动回滚,也就是添加用户失败,然而当我们查询数据库时,却发现事务并未执行回滚操作数据库的数据如下图所示:

2.timeout 超时

当在 @Transactional 上,设置了一个较小的超时时间时,如果方法本身的执行时间超过了设置的 timeout 超时时间,那么就会导致本来应该正常插入数据的方法执行失败,示例代码如下:

@Transactional(timeout = 3) // 超时时间为 3s
@RequestMapping("/save")
int save(UserInfo userInfo) throws InterruptedException {
    // 非空效验
    if (userInfo == null ||
        !StringUtils.hasLength(userInfo.getUsername()) ||
        !StringUtils.hasLength(userInfo.getPassword()))
        return 0;
    int result = userService.save(userInfo);
    return result;
}

UserService 的 save 方法实现如下:

public int save(UserInfo userInfo) throws InterruptedException {
    // 休眠 5s
    TimeUnit.SECONDS.sleep(5);
    int result = userMapper.add(userInfo);
    return result;
}

以上程序的运行结果如下:

数据库没有正确的插入数据,如下图所示:

3.代码中有 try/catch

在前面 @Transactional 的执行流程中,我们提到:当方法中出现了异常之后,事务会自动回滚。然而,如果在程序中加了 try/catch 之后,@Transactional 就不会自动回滚事务了,示例代码如下:

@Transactional
@RequestMapping("/save")
public int save(UserInfo userInfo) throws InterruptedException {
    // 非空效验
    if (userInfo == null ||
        !StringUtils.hasLength(userInfo.getUsername()) ||
        !StringUtils.hasLength(userInfo.getPassword()))
        return 0;
    int result = userService.save(userInfo);
    try {
        int num = 10 / 0; // 此处设置一个异常
    } catch (Exception e) {
    }
    return result;
}

以上程序的运行结果如下:

此时,查询数据库我们发现,程序并没有执行回滚操作,数据库中被成功的添加了一条数据,如下图所示:

4.调用类内部 @Transactional 方法

当调用类内部的 @Transactional 修饰的方法时,事务是不会生效的,示例代码如下:

@RequestMapping("/save")
public int saveMappping(UserInfo userInfo) {
    return save(userInfo);
}
@Transactional
public int save(UserInfo userInfo) {
    // 非空效验
    if (userInfo == null ||
        !StringUtils.hasLength(userInfo.getUsername()) ||
        !StringUtils.hasLength(userInfo.getPassword()))
        return 0;
    int result = userService.save(userInfo);
    int num = 10 / 0; // 此处设置一个异常
    return result;
}

以上代码我们在添加方法 save 中添加了 @Transactional 声明式事务,并且添加了异常代码,我们预期的结果是程序出现异常,事务进行自动回滚,以上程序的执行结果如下:

然而,当我们查询数据库时发现,程序执行并不符合我们的预期,添加的数据并没有进行自动回滚操作,如下图所示:

5.数据库不支持事务

我们程序中的 @Transactional 只是给调用的数据库发送了:开始事务、提交事务、回滚事务的指令,但是如果数据库本身不支持事务,比如 Mysql 中设置了使用 MyISAM 引擎,那么它本身是不支持事务的,这种情况下,即使在程序中添加了 @Transactional 注解,那么依然不会有事务的行为,这就是巧妇也难为无米之炊吧。

总结

当声明式事务 @Transactional 遇到以下场景时,事务会失效:

  • 非 public 修饰的方法;
  • timeout 设置过小;
  • 代码中使用 try/catch 处理异常;
  • 调用类内部 @Transactional 方法;
  • 数据库不支持事务。

到此这篇关于Spring @Transactional事务失效的原因分析的文章就介绍到这了,更多相关Spring @Transactional事务失效内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Spring @Transactional事务失效的原因分析

本文链接: https://lsjlt.com/news/167573.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Spring @Transactional事务失效的原因分析
    目录前言1.非 public 修饰的方法2.timeout 超时3.代码中有 try/catch4.调用类内部 @Transactional 方法5.数据库不支持事务总结前言 一个程...
    99+
    2024-04-02
  • Spring事务注解@Transactional失效的八种场景分析
    首先说一下最近自己遇到的一个坑: @Transactional service A(){ try{ insert(); serviceB.update(); }catch(){...
    99+
    2024-04-02
  • 从Spring源码解析事务失效的原因
    目录一、前言二、方法不是 public 的三、内部方法间调用导致事务失效四、异常类型是否配置正确五、异常被catch住一、前言 1.Bean是否是代理对象 2.入口函数是否是pub...
    99+
    2024-04-02
  • 解读Spring接口方法加@Transactional失效的原因
    目录问题总结问题 今天项目测试一个方法的时候,发现日志报错 日志报错大致如下:Connection is read-only. Queries leading to data mod...
    99+
    2023-03-13
    Spring接口 @Transactional失效的原因 @Transactional失效
  • Spring事务失效的原因是什么
    本篇内容主要讲解“Spring事务失效的原因是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring事务失效的原因是什么”吧!1、数据库引擎不支持事务这...
    99+
    2024-04-02
  • Spring事务失效的示例分析
    这篇文章给大家分享的是有关Spring事务失效的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Spring事务最终依赖的数据库的事务,如果用的是mysql的话,执行引擎要是innodb;因为只有innoD...
    99+
    2023-06-29
  • Spring事务失效的场景分析
    这篇文章主要介绍“Spring事务失效的场景分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring事务失效的场景分析”文章能帮助大家解决问题。1)未被Spring管理使用Spring事务的前...
    99+
    2023-07-02
  • @Transactional 注解失效的原因有哪些
    @Transactional 注解失效的原因有哪些,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、事务事务管理在系统开发中是不可缺少的一...
    99+
    2024-04-02
  • spring事务注解失效的原因有哪些
    以下是一些可能导致Spring事务注解失效的原因:1. 配置问题:可能是由于配置文件的错误或不完整,导致Spring无法正确解析和处...
    99+
    2023-08-23
    spring
  • 分析Springboot中嵌套事务失效原因详解
    首先两个事务方法,其中一个调用另一个。 @Transactional(rollbackFor = Exception.class) public void trance() { ...
    99+
    2024-04-02
  • 聊聊spring @Transactional 事务无法使用的可能原因
    spring transaction 建议 Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解, 而不要使用在类所要实现的任何接口上。你当然...
    99+
    2024-04-02
  • Spring事务@Transactional注解四种不生效案例场景分析
    目录背景示例代码1. 类内部访问2. 私有方法3. 异常不匹配4. 多线程父线程抛出异常子线程抛出异常源码解读@Transactional 执行机制private 导致事务不生效原因...
    99+
    2024-04-02
  • Spring事务失效之常见场景分析
    目录一、事务方法访问修饰符非public,导致事务失效二、@Transactional注解的方法抛出的异常不是spring的事务支持的异常,导致事务失效三、数据表本身是不支持事务,导...
    99+
    2023-05-17
    Spring事务失效 Spring事务失效场景 Spring事务 事务失效常见场景
  • Spring事务失效的一种原因关于this调用的问题
    PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启事务; PROPAGATION_REQUIRES_NEW:总是开启一...
    99+
    2024-04-02
  • Java spring事务及事务不生效的原因详解
    目录注解@Transactional的属性参数propagation事务的传播机制isolation事务的隔离级别常用数据库的默认隔离级别readOnly事务的读写性事务的只读性概念...
    99+
    2024-04-02
  • Spring事务回滚失败的原因有哪些
    Spring事务回滚失败的原因有以下几种情况: 事务配置错误:可能是因为事务管理器配置不正确,或者在事务方法上没有正确标注@Tr...
    99+
    2024-03-01
    Spring
  • spring中@Transactional的失效场景有哪些
    小编给大家分享一下spring中@Transactional的失效场景有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、失效场景集一:代理不生效Spring...
    99+
    2023-06-22
  • 探索Java中private方法添加@Transactional事务未生效原因
    现在产品期望用户创建和保存逻辑分离:把User实例的创建和保存逻辑拆到两个方法分别进行。然后,把事务的注解 @Transactional 加在保存数据库的方法上。 @Servic...
    99+
    2024-04-02
  • hal.dll 丢失的原因分析
    一客户机器远程不上 接显示器一看 提示 hal.dll丢失 上网一查 hal.dll是Windows硬件提取层模块,开机后,系统无法进入,出现错误提示:请重新安装以上文件的拷贝:windwos root\system32...
    99+
    2023-05-24
    hal.dll 丢失 原因
  • spring中12种@Transactional的失效场景(小结)
    目录一、失效场景集一:代理不生效二、失效场景集二:框架或底层不支持的功能三、失效场景集三:错误使用@Transactional四、总结数据库事务是后端开发中不可缺少的一块知识点。Sp...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作