Spring事务的1道面试题

news2024/11/25 15:33:55

每次聊起Spring事务,好像很熟悉,又好像很陌生。本篇通过一道面试题和一些实践,来拆解几个Spring事务的常见坑点。

原理

Spring事务的原理是:通过AOP切面的方式实现的,也就是通过代理模式去实现事务增强。

具体过程是:对包含@Transactional注解的方法进行拦截,然后重写,重新在方法里加入异常回滚的逻辑。而且,每个线程都是独立管理自己的事务,相互隔离。

原理简单,使用起来也简单,也就是在方法上打上@Transactional注解,然后事务就正常生效了。也很少有人去验证异常情况下是否能真正的回滚。

Spring事务让我熟悉的地方是哪哪看起来都简单,让我陌生的地方使用时的变种较多,有时候莫名其妙的不生效。

源码

以上原理的相关源码如下:

实践出真知

但是 [半支烟] 偶尔会在编码过程中发现有些场景下的事务是失效的,总有些情况让你想不到,总有一些坑点等你去跳。

[半支烟] 觉得验证事务的最好方式就是:记住基本原则 + 动手实践。记住基本原则可以快速处理常规问题,动手实践可以验证偏门问题或者不确定的问题。

几种事务不生效的用法

如下是常见的几种Spring事务不生效的用法,有空的读者一定要牢记,对日常编码很有帮助,同时面试时也能说几句。

  • private方法

Spring是通过AOP代理的方式实现事务增强的,但是private方法无法被代理,所以在private方法上打@Transactional注解是不生效的。

  • final、static修饰的方法

和private方法类似,final和static修饰的方法也无法被代理,所以@Transactional注解也不生效。

因为,static是属于类方法,final修饰的方法无法被重写,自然也就无法植入事务增强代码。

  • Bean对象没有被Spring托管

某个类一定要被Spring托管,那才能通过@Transactional注解去增强事务。如果只有@Transactional注解,而没有把类交给Spring托管,事务也是不生效的。类似如下情况:

// 此处没有@Service注解,此类不被spring托管,及时有@Transactional也不生效
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Transactional
    public final void createAndUpdateUser() {
        createUser();
        updateUserById();
    }

    public void createUser() {
        User user = new User();
        user.setId(2L);
        user.setName("test2");
        user.setEmail("test2" + "@test.com");
        userMapper.insert(user);
        System.out.println("create user");
    }

    public void updateUserById() {
        User user = userMapper.findById(1L);
        user.setName("admin1");
        userMapper.update(user);
        int i = 1 / 0; // 此处会抛出异常
        System.out.println("update user");
    }
}
  • 异常被吞掉

如果在业务代码里,通过try......catch捕获了异常,同时又没有继续抛出异常时,Spring事务也是不生效的。

因为代理增强的逻辑就是要发现了异常,才能回滚事务。如果异常被方法本身吞掉了,则代理会认为没有异常,从而无法回滚。

  • 非RuntimeException异常

Spring事务默认会回滚RuntimeException 及其子类,以及 Error 类型的异常。如果是其余异常,则不会回滚。源码处可见:

这种非RuntimeException异常场景下,需要做2个动作从而保证事务回滚。

  1. 捕获异常,然后抛出自定义异常。
  2. 自行在@Transactional注解中增加@Transactional(rollbackFor = XxxxxxxException.class)属性。或者直接使用rollbackFor = Exception.class,也就免去了第一步。
  • 异步线程的场景

多个线程的场景下,只需要牢记每个线程只管理自己的事务即可。每个线程都有一个独立的事务上下文,存在ThreadLocal中,所以事务信息在不同线程之间是隔离的。

  • 重灾区:在同一个类中调用本类的方法

这个失效场景,是最容易出错的,而且变种还多。在同一个类中调用本类的方法时,牢记以下2点,即可破局:

  1. 是否会开启事务依赖此类的第一个被外部调用的方法。如果此类的第一个被外部调用的方法有@Transactional注解,那事务生效。
  2. 调用自己内部方法时,采用的是this.xxxMethod()的方式,这种方式是不会走AOP代理的,所以被调用的内部方法的@Transactional注解不生效。

如果确实需要调用内部方法,并且要事务生效的话,那只能将被调用的内部方法独立到新的类中,同时交给Spring管理。

一道面试题

以上关于事务不生效的用法都比较好记,只有在同一个类中调用本类的方法场景下存在多种变种。具体请看这道面试题。请问以下createAndUpdateUser方法的事务生效吗?

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Transactional
    public final void createAndUpdateUser() { //注意这里有final修饰
        createUser();
        updateUserById();
    }

    @Transactional
    public void createUser() {
        User user = new User();
        user.setId(2L);
        user.setName("test2");
        user.setEmail("test2" + "@test.com");
        userMapper.insert(user);
        System.out.println("create user");
    }


    @Transactional(rollbackFor = Exception.class)
    public void updateUserById() {
        User user = userMapper.findById(1L);
        user.setName("admin1");
        userMapper.update(user);
        int i = 1 / 0; // 此处会抛出异常
        System.out.println("update user");
    }
}

如果按照重灾区:在同一个类中调用本类的方法里提到的2个原则,则事务全部生效。

如果按照final、static修饰的方法里提到的原则,则事务全部不生效。

那结果如何呢?结果是以上方法的事务全部生效。

为什么呢?这里在补充一个原则:final修饰的方法如果带上@Transactional注解,事务情况按照被调用的方法自身的事务托管情况而定。

因为以上代码中的createUser方法和updateUserById方法,都有@Transactional注解,所以都生效。

这种特殊情况也实在是让人瞠目,不过只需要牢记以上几种不生效的用法即可,谁没事儿写这种@Transactionalfinal的代码呢?除了面试会问......

总结

本篇主要聊了几种事务不生效的用户,有兴趣的读者可以记一下。同时,还出了一道特殊场景的面试题,供读者自行实践。希望对你有帮助!

本篇完结!欢迎 关注、加V交流、全网可搜(程序员半支烟)

原文链接:Spring事务的1道面试题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2202244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年诺贝尔物理学奖

2024年,诺贝尔物理学奖没有颁给物理学家,而是授予了两位计算机科学家,表彰他们在神经网络领域的开创性工作,这项研究成为了我们今天所称的人工智能的基础。这标志着物理学与计算机科学之间的深度融合。 获奖者约翰霍普菲尔德和杰弗…

财政警钟敲响!CBO预测:美国2024财年赤字预计达1.8万亿美元

KlipC报道:美国国会预算办公室(CBO)近日发布报告显示,2024财年(2023年10月1日至2024年9月30日),美国联邦政府预算赤字高达1.8万亿美元,与上一财年相比增加了1390亿美元。据CBO预测&a…

转型AI产品经理需要掌握的硬知识、经理能力模型和常见AI概念梳理

近几年,从亚马逊, Facebook,到谷歌,微软,再到国内的BAT,全球最具影响力的技术公司都将目光转向了人工智能( AI )。2016年 AlphaGo 战胜李世石,把公众的目光也聚集到了人工…

IROS24新鲜出炉:PRL-Track,最先进的无人机视觉目标跟踪系统!

导读: 近年来,随着无人机技术的飞速发展,视觉目标跟踪在无人机的自主应用中扮演着越来越重要的角色,然而,在复杂多变的环境中,实现高精度的目标跟踪并非易事。无人机在飞行过程中,常常会遇到目标…

介绍几个电池充电管理芯片(TP4056、SGM40561)

TP4056 上一篇我们介绍了个TP4055,那么跟TP4055相比,TP4056肯定是做了升级的。 首先是有最高1000mA的充电电流,而TP4055是500mA。 一般来说我们尽可能的让充电电流接近电池容量的一半,这样对电池比较好。 充电电压都是4.2V。 …

winform实现托盘语音提醒

测试环境: visual studio 2022 window 10 .net framework 4.6 本文实现的功能有: 1 托盘最小化 2 语音定时播放 3 检测到操作系统被客户点静音后,需要程序控制开启音量(在运行过程中,由于语音重复播放,客户很烦&#…

【Protobuf】基本使用总结+项目实践

概述 序列化与反序列化 网络传输中使用,可以实现将对象转换为二进制序列,然后将二进制序列转换为对象,这一个交互的过程就是序列化。生成的数据,持久化存储到磁盘上的过程,也需要经过序列化和反序列化才可以实现。 序…

SpringBoot实现的美发门店客户关系管理(CRM)系统

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…

浅谈2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者

目录 1.概述 1.1. 跨学科的融合 1.2. 推动科学研究的工具 1.3. 对科学界的激励 1.4. 技术的社会影响 2.机器学习与神经网络的发展前景 2.1.具体应用与作用 2.1.1. 医疗健康 2.1.2. 金融 2.1.3. 制造业 2.1.4. 交通与物流 2.1.5. 零售 2.2.未来展望 2.3.科学研究与…

C# 实现调用函数,打印日志(通过反射代理、非IOC)

🎈个人主页:靓仔很忙i 💻B 站主页:👉B站👈 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:C# 🤝希望本文对您有所裨益,如有不足之处&#xff…

宝塔面板配置FTP服务结合内网穿透实现其他设备远程连接上传文件

文章目录 前言1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结 5. 固定FTP公网地址6. 固定FTP地址连接 前言 本文主要介绍宝塔FTP文件传输服务如何搭配内网穿透工具,实现随时随地远程连接局域网环境搭建的宝塔FTP文件服务并进行文件…

电商数据淘宝/京东/1688商品SKU数据采集||电商API接口

电商数据采集接口数据分析是一个涉及多个步骤的过程,以下是一个详细的指南: 一、数据采集接口的选择与接入 选择合适的电商数据采集接口: 根据需求选择提供所需数据的电商平台接口。考虑接口的稳定性、数据更新频率及准确性。 接口接入准备&…

《网络数据安全管理条例》正式公布,规范数据处理活动,保障网络数据安全

近日,《网络数据安全管理条例》(以下简称《条例》)正式公布,自2025年1月1日起施行。 《条例》旨在规范网络数据处理活动,保障网络数据安全,促进网络数据依法合理有效利用,保护个人、组织的合法权…

java时间复杂度与空间复杂度的排序

怎么理解时间复杂度和空间复杂度 时间复杂度和空间复杂度一般是针对算法而言,是衡量一个算法是否高效的重要标准。先纠正一个误区,时间复杂度并不是算法执行的时间,再纠正一个误区,算法不单单指冒泡排序之类的,一个循…

获取期货股票历史数据以及均线策略分析

【数据获取】银河金融数据库(yinhedata.com)能够获取国内外金融股票、期货历史行情数据,包含各分钟级别。 【搭建策略】均线策略作为一种广泛应用于股票、期货等市场的技术分析方法,凭借其简单易懂、操作性强等特点,深…

CV图像处理小工具——json文件转P格式mask

CV图像处理小工具——json文件转P格式mask import cv2 import json import numpy as np import osdef func(file_path: str) -> np.ndarray:try:with open(file_path, moder, encoding"utf-8") as f:configs json.load(f)# 检查JSON是否包含必要的字段if "…

【专题】2024年中国电商市场研究报告合集PDF分享(附原数据表)

原文链接:https://tecdat.cn/?p37835 在全球电商持续发展的背景下,中国电商市场面临新态势。 增长压力与机遇并存,从综合电商与直播电商发展的放缓,到企业 3C 数码商用品电商采购的趋势,以及零售业拥抱“性价比时代…

校园网站设计怎么做

校园网站设计是一项复杂而又具有挑战性的任务,因为它需要考虑到学校内各种不同的需求和利益。一个成功的校园网站应该能够满足学生、教职员工、家长和管理人员的需求,同时提供清晰、易用且富有吸引力的界面。以下是一些设计校园网站的关键方面&#xff0…

腾讯全文检索引擎 wwsearch 正式开源

背景 企业微信作为典型企业服务系统,其众多企业级应用都需要全文检索能力,包括员工通讯录、企业邮箱、审批、汇报、企业CRM、企业素材、互联圈子等。下图是一个典型的邮件检索场景。 由于过去几年业务发展迅速,后台检索架构面临挑战&#xf…

学霸都在用的秘密武器!盘点3款语音识别转文字软件,学习力MAX!

现在科技这么发达,手写笔记好像越来越不流行了。在这个什么都讲究快的时代,怎么又快又好地记下重要信息,是大家都想要的。正好,现在市面上有很多能把语音转换成文字的工具,它们特别有用,正在慢慢改变我们学…