我的编程空间,编程开发者的网络收藏夹
学习永远不晚

使用@Transactional 设置嵌套事务不回滚

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

使用@Transactional 设置嵌套事务不回滚

@Transactional 设置嵌套事务不回滚


    @Transactional(rollbackFor = Exception.class)
    public void testA(RequestSchedulingVO requestSchedulingVO) {
     ...业务...
        BService.testB(param);
    }

@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false, noRollbackFor = BusinessException.class)
//    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void testB(Long param) throws BusinessException {
        ...业务...
        try{
        }cach(Exception e){
         throw new BusinessException(BaiduFaceErrorCode.FACE_CREATE_CONVERSATION_ERROR);
        }
    }

这里的事务要求是方法testB报错(BusinessException异常)时,testB事务不回滚,testA事务回滚.

方案一:

testB设置事务为REQUIRES_NEW(创建一个新的事务,如果当前存在事务,则把当前事务挂起),并设置不回滚的异常类

方案二:

testB设置事务为NOT_SUPPORTED(以非事务方式运行,如果当前存在事务,则把当前事务挂起)。

@Transactional回滚问题(try catch、嵌套)

Spring 事务注解 @Transactional 本来可以保证原子性,如果事务内有报错的话,整个事务可以保证回滚,但是加上try catch或者事务嵌套,可能会导致事务回滚失败。测试一波。

准备

建两张表,模拟两个数据操作


CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `age` smallint(3) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
 
CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

测试

根据排列组合原理,我们进行四种测试:1、无try catch、无嵌套;2、有try catch、无嵌套;3、无try catch、有嵌套;4、都有。

最简单测试

如果我们单纯@Transactional,事务可以正常回滚吗?


    @GetMapping("/saveNormal0")
    @Transactional
    public void saveNormal0() throws Exception {
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:"+age);
        userService.save(user);
        throw new RuntimeException();
    }

如果事务内报了RuntimeException错误,事务可以回滚。


    @GetMapping("/saveNormal0")
    @Transactional
    public void saveNormal0() throws Exception {
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:"+age);
        userService.save(user);
        throw new Exception();
    }

如果事务内报了Exception错误(非RuntimeException错误),事务不可以回滚。


    @GetMapping("/saveNormal0")
    @Transactional( rollbackFor = Exception.class)
    public void saveNormal0() throws Exception {
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:"+age);
        userService.save(user);
        throw new Exception();
    }

如果是Exception错误(非RuntimeException),加上 rollbackFor = Exception.class 参数也可以实现回滚。

结论一:对于@Transactional可以保证RuntimeException错误的回滚,如果想保证非RuntimeException错误的回滚,需要加上rollbackFor = Exception.class 参数。

try catch 影响

经过博主多种情况测试,发现try catch对回滚这个事本身没有什么影响,结论一照样成立。try catch只是对异常是否可以被@Transactional 感知 到有影响。如果错误抛到切面可以感知到的地步,那就可以起作用。


    @GetMapping("/saveTryCatch")
    @Transactional( rollbackFor = Exception.class)
    public void saveTryCatch() throws Exception{
        try{
            int age = random.nextInt(100);
            User user = new User().setAge(age).setName("name:"+age);
            userService.save(user);
            throw new Exception();
        }catch (Exception e){
            throw e;
        }
    }

比如上面一段代码就回滚了。


    @GetMapping("/saveTryCatch")
    @Transactional( rollbackFor = Exception.class)
    public void saveTryCatch() throws Exception{
        try{
            int age = random.nextInt(100);
            User user = new User().setAge(age).setName("name:"+age);
            userService.save(user);
            throw new Exception();
        }catch (Exception e){
        }
    }

然而,将catch中的错误不继续网上抛,切面无法感知到错误,无法进行处理,那么事务就无法回滚了。

结论二:try catch只是对异常是否可以被@Transactional 感知 到有影响。如果错误抛到切面可以感知到的地步,那就可以起作用。

事务嵌套 影响

首先经过实验,结论一仍然成立,即,当不加上rollbackFor = Exception.class 的时候,无论内外报RuntimeException,都会回滚;无论内外报 非RuntimeException 错误,都不会回滚。如果加上rollbackFor = Exception.class,无论内外怎么报错,都会回滚。这些代码就不给出了。接下来,试下下面两种情况:


   @GetMapping("/out")
    @Transactional( rollbackFor = Exception.class)
    public void out() throws Exception{
        innerService.inner();
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:" + age);
        userService.save(user);
        throw new Exception();
    }
    @Transactional
    public void inner() throws Exception{
        Role role = new Role();
        role.setRoleName("roleName:"+new Random().nextInt(100));
        roleService.save(role);
//        throw new Exception();
    }

情况一,外面事务加上rollbackFor = Exception.class,里面事务不加,测试内外分别报错的情况(为了简化代码量,只给出了外面报错的代码),都可以回滚。因为,无论如何,错误都抛给了外面那个事务进行处理,而外面那个加上了rollbackFor = Exception.class,具备处理非RuntimeException错误的能力,所以都可以让事务进行正常回滚。

下面看情况二,里面的事务加上rollbackFor = Exception.class,外面不加,外面报错。


   @GetMapping("/out")
    @Transactional
    public void out() throws Exception{
        innerService.inner();
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:" + age);
        userService.save(user);
        throw new Exception();
    }
    
    @Transactional( rollbackFor = Exception.class)
    public void inner() throws Exception{
        Role role = new Role();
        role.setRoleName("roleName:"+new Random().nextInt(100));
        roleService.save(role);
    }

事务都无法回滚,这是我们有个疑问,里面的事务明明有很强的处理能力啊,为什么和外面一起回滚失败呢,别着急,等等聊这个。

然后试下里面报错:


    @GetMapping("/out")
    @Transactional
    public void out() throws Exception{
        innerService.inner();
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:" + age);
        userService.save(user);
    }
     @Transactional( rollbackFor = Exception.class)
    public void inner() throws Exception{
        Role role = new Role();
        role.setRoleName("roleName:"+new Random().nextInt(100));
        roleService.save(role);
        throw new Exception();
    }

咦,这回都进行了正常的回滚。我的天,这回外面没有处理能力,为什么接受里面抛出来的错误,也进行了回滚!!!看上去,就好像里外事务总是同生共死的对不对?原来,@Transactional还有个参数,看下源码,这个注解还有默认值:


Propagation propagation() default Propagation.REQUIRED;

REQUIRED的意思是说,事务嵌套的时候,如果发现已经有事务存在了,就加入这个事务,而不是新建一个事务,所以根本就不存在两个事务,一直只有一个!至于,此参数其他值,本文不进行测试。回到上面的问题,当外面报错的时候,此时查看事务,没有增加rollbackFor = Exception.class参数,即没有处理非RuntimeException能力,所以代码走完,貌似“两个事务”,都回滚失败了。当里面报错的时候,事务已经添加上了处理非RuntimeException能力,所以,代码走完就回滚成功了。

结论三:由于REQUIRED属性,“两个事务”其实是一个事务,处理能力看报错时刻,是否添加了处理非RuntimeException的能力。

try catch和事务嵌套 共同影响

在结论一二三成立的条件下,探索共同影响的问题就简单多了,由于情况太多,就不进行过多的代码展示了。

结论

结论一:

对于@Transactional可以保证RuntimeException错误的回滚,如果想保证非RuntimeException错误的回滚,需要加上rollbackFor = Exception.class 参数。

结论二:

try catch只是对异常是否可以被@Transactional 感知 到有影响。如果错误抛到切面可以感知到的地步,那就可以起作用。

结论三:

由于REQUIRED属性,“两个事务”其实是一个事务,处理能力看报错时刻,是否添加了处理非RuntimeException的能力。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

使用@Transactional 设置嵌套事务不回滚

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么使用@Transactional设置嵌套事务不回滚

本篇内容介绍了“怎么使用@Transactional设置嵌套事务不回滚”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!@Transaction
2023-06-20

Java 事务注解@Transactional回滚(try catch、嵌套)问题

这篇文章主要介绍了Java @Transactional回滚(try catch、嵌套)问题,Spring 事务注解 @Transactional 本来可以保证原子性,如果事务内有报错的话,整个事务可以保证回滚,但是加上try catch或者事务嵌套,可能会导致事务回滚失败
2022-11-13

轻量应用服务器流量不足怎么回事呢苹果13怎么设置

轻量应用服务器流量不足是由于服务器网络连接速度较慢,导致应用程序无法正常运行,从而导致AppStore网站访问缓慢、下载缓慢,以及用户在购买App时无法进行支付。为了解决这种情况,您需要检查服务器网络连接速度,以确保其始终是畅通的。您可以使用以下步骤:重启您的服务器连接:在使用Windows操作系统和苹果手机时,请尝试在设置中启用“自动连接到Internet”选项,以便在您停用网络连接时自
2023-10-26

轻量应用服务器端口用不了怎么回事儿呀苹果13怎么设置

如果您的应用服务器端口正在使用其他端口,可能会导致无法连接到您的iOS设备。请联系您的应用开发商或应用程序提供商以获取正确的端口选择。如果您无法使用应用服务器端口,可以尝试以下几个步骤:检查应用程序的源代码,确定是否有任何端口或其他协议可能与应用程序的通信。检查应用程序的用户设置或库设置,确保它们已正确配置。检查应用程序与其他服务的依赖项,确保它们都正确安装。如果依赖项不存在,请将其添加
2023-10-26

轻量应用服务器登录不了怎么回事呢苹果手机怎么设置

如果您的应用服务器登录失败,那么很可能是由于您的手机系统版本过旧或者操作系统权限不足引起的。以下是一些可能有帮助的解决方案:1.尝试升级您的操作系统或更换新操作系统:如果您的操作系统版本过旧或者系统权限不足,那么尝试升级您的系统或更换新操作系统可能会解决登录问题。在升级之前,请确保您的手机已经更新到最新版本的操作系统。2.检查您的手机是否被恶意软件感染:有时,应用程序服务器可能会出现问题或者
2023-10-26

轻量应用服务器登录不上怎么回事呢苹果手机怎么设置

轻量应用服务器(LightweightApplicationServer,LSP)是一种轻量级的应用服务器,它能够支持各种应用,包括Web、游戏、数据库和云服务等。轻量应用服务器通常具有以下特点:支持多种应用程序:轻量应用服务器能够支持各种应用程序,包括Web应用程序、游戏、数据库应用程序和其他轻量级应用,同时还可以与其他轻量级应用服务器进行集成。轻量化设计:轻量应用服务器采用了轻量化的设
2023-10-26

轻量应用服务器登录不了怎么回事呀苹果手机怎么设置

轻量应用服务器登录不了可能有多种原因导致,以下是一些可能的解决方法:1.检查网络连接:尝试重新检查网络连接,确保连接正确并尝试使用网络。确保连接稳定,并且网络设置正常。2.检查用户名和密码:如果登录时需要输入用户名和密码,请确保用户名和密码的安全性。可以使用强密码或密码生成器等方式来解决这些问题。3.检查应用程序:检查应用程序是否被正确安装,并且安装的路径是否正确。如果应用程序未正常安装或
2023-10-26

轻量应用服务器流量不足怎么回事呀苹果手机怎么设置

一、合理设置应用程序服务器配置文件应用程序服务器配置文件是应用程序在运行时所需要的资源。合理设置应用程序服务器配置文件可以有效提高应用程序的性能和数据传输速度。在应用程序服务器配置文件中,我们可以添加一些限制性的配置项,如CPU使用率、内存使用率、网络带宽等。这些配置项可以根据应用程序的运行情况进行动态调整,以达到优化
轻量应用服务器流量不足怎么回事呀苹果手机怎么设置
2023-10-28

轻量应用服务器流量不足怎么回事呢苹果手机怎么设置

轻量应用服务器流量不足是由于多种原因引起的,以下是一些可能的解决方案:应用程序内存不足:请确保应用程序能够快速访问您的数据,并避免在不需要的情况下保存过多的用户数据。网络连接问题:请确保您的网络连接正常,并确保您的电脑有足够的带宽来处理您需要的数据。如果您使用较慢的网络,请尝试使用其他网络。应用程序崩溃:请确保您的应用程序能够正常运行,并且不会崩溃以致影响其他应用程序。系统更新失败:您
2023-10-26

轻量应用服务器登录不上怎么回事呀苹果手机怎么设置

轻量应用服务器登录不上可能有多种原因导致,以下是一些可能的解决方法:1.尝试重新启动应用程序:首先,尝试重新启动应用程序或尝试清除浏览器缓存,以便重新加载登录页面。如果仍然无法解决问题,请尝试在安全模式下重新启动应用程序或清除浏览器缓存。2.使用新的浏览器或软件:有时,您可能会发现应用程序或浏览器没有正确更新,导致您无法访问您的账户。尝试升级或更新您的应用或浏览器以满足最新版本的要求。3.
2023-10-26

轻量应用服务器流量不足怎么回事呢苹果12手机怎么设置

轻量应用服务器流量不足是由于苹果手机的一些应用程序或服务在使用时需要更多的网络带宽和加速器。在这种情况下,您可以尝试以下步骤:重新启动手机:如果您的iPhone无法重新启动,请尝试重新启动手机并等待几分钟,这将有助于减少数据流量消耗,同时使应用程序的加速器更为流畅。手动调整应用程序的网络设置:一些应用程序可能会使用特定的网络设置,例如Wi-Fi或蜂窝数据。您可以手动对这些设置进行调整以确保您的应用程序能够通过所需...
2023-10-26

轻量应用服务器登录不了怎么回事呀苹果13手机怎么设置

如果您的应用服务器登录失败,那么很可能是因为您的手机设置了不正确的权限。如果您想设置您的应用服务器为允许登录状态,以下是可能的解决方案:检查您的设置。您可以按照以下步骤检查您的设置是否正确:进入应用程序,然后按照屏幕上的提示来更改您的设置。如果您遇到了错误消息,请返回应用程序并按照屏幕上的提示进行操作。检查您的账户和密码。您可能已经忘记了您的账户和密码并且无法通过应用程序或网站来访问它们。
2023-10-26

轻量应用服务器登录不上怎么回事呢苹果13手机怎么设置

对于轻量应用服务器登录不上的问题,可能有多种原因导致,以下是一些可能的解决方法:检查网络连接:确保您的设备已连接到互联网,并且网络连接稳定。您可以尝试使用其他设备连接到同一网络,以确定问题是否出在您的设备上。检查服务器状态:如果您无法登录到轻量应用服务器,可能是服务器出现了问题。您可以尝试联系服务器管理员或者查看服务器状态是否正常。检查登录凭证:确保您输入的用户名和密码是正确的,并且没有
2023-10-26

轻量应用服务器登录不上怎么回事呀苹果12手机怎么设置

如果您的轻量应用服务器登录不上,可能是由于以下原因之一导致的:连接问题:轻量应用服务器通常需要与云服务器相连才能正常运行,如果连接出现问题或者服务器无法提供足够的带宽,就很容易出现登录问题。网络问题:如果服务器连接不稳定或者出现故障,很可能会导致无法登录。服务器配置问题:服务器的配置可能存在问题,例如服务器负载过高、服务器配置错误等,也会导致登录问题。网络防火墙或过滤器配置问题:如果轻
2023-10-26

轻量应用服务器登录不了怎么回事呀苹果12手机怎么设置

如果您的AleMobileSpaces应用服务器登录不了,可能有以下几个原因:安全性问题:您需要确保您的设备或SIM卡安全,以避免黑客利用该功能进行恶意攻击或数据窃取。网络连接问题:请确保您的网络连接稳定,并且您使用的是WLAN或GPRS网络,而不是5G或3G网络。如果网络不稳定,可能会导致应用服务器登录失败。应用版本问题:如果您的AleMobileSpaces应用版本比较旧或存在其他问
2023-10-26

轻量应用服务器流量不足怎么回事呢苹果13手机怎么设置

轻量应用服务器流量不足是由于一些轻量应用服务器流量不足导致的。以下是一些可能的解决方法:检查您的应用程序使用的服务或套件的服务条款和条件以及相关费用。确保您只启用必要的服务或套件,并确保您没有使用不必要的服务或套件。如果是应用程序服务器,尝试将应用程序添加到应用程序仓库中或者尝试使用应用程序服务器的服务。这将帮助更好地跟踪应用程序的性能。尝试使用一些更好的应用程序编程接口(API)来解决这个问题。例如,...
2023-10-26

轻量应用服务器登录不上怎么回事呀苹果13手机怎么设置

如果您的轻量应用服务器登录不上,可能是由于以下原因之一导致的:您的操作系统版本过低:如果您的操作系统版本较低,或者运行的是一些旧版本的应用程序,那么您可能无法识别轻量应用服务器。应用程序崩溃:如果您的应用程序崩溃或者出现闪退,那么可能是由于轻量应用服务器存在故障或崩溃导致的。服务器配置不正确:如果您的服务器配置不正确,那么也可能导致轻量应用服务器登录不正常。应用程序权限不足:如果应用程
2023-10-26

轻量应用服务器流量不足怎么回事呀苹果13手机怎么设置

轻量应用服务器流量不足是由于苹果公司在设计和维护轻量应用服务器时没有充分考虑到移动网络设备的性能和覆盖范围。通常,移动网络设备在没有足够数据流量来访问应用程序时就会出现流量不足的情况。为解决轻量应用服务器流量不足的问题,可以尝试以下措施:升级iPhone或iPad的iOS系统。iPhone和iPad系统的性能可能较差,需要升级到最新版本才能保证应用程序在移动网络设备上正常运行。限制应用程序的网络使用时间。在轻量应用服务...
2023-10-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录