【数据库】@Transactional用法详解

先看代码,你觉得运行结果是什么?

public class TestService {@Autowiredprivate TestService service;@Transactionalpublic void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}}@Transactionalpublic void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);// 异常代码System.out.println("".substring(4));}
}

答案是test31插入了一条数据,test32也插入了一条数据。

往下看……

一、首先要确保注解是生效的

示例一:

public class TestService1 {@Autowiredprivate TestService2 service2;@Transactional // 生效public void test1(){service2.test2();}
}public class TestService2 {@Transactional // 不生效public void test2() {System.out.println("test2");}
}
这里的test1的@Transactional生效,test2()的@Transactional不生效,嵌套时,只有最外层的生效。

示例二:

public class TestService1 {public void test1(){test2();}@Transactional // 不生效public void test2() {System.out.println("test2");}
}
这里的test2()的@Transactional不生效,原因看后面原理

示例三:

public class TestService1 {@Autowiredprivate TestService1 service;public void test1(){service.test2();}@Transactional // 生效public void test2() {System.out.println("test2");}
}
这里自己注入自己后,就生效了,看下面原理

原理

        因为spring里是通过代理类来调用,所以自己注入自己就可以(spring自身解决了循环依赖问题),或者还可以通过获取代理类来调用。


二、代码异常时,执行顺序


从发生异常的地方开始,往上抛
1、如果先遇到try catch,那么就被catch住(如果catch里面不再往外抛异常,那就不会被事务抓到)
2、如果先遇到事务,那就会回滚

三、发生回滚时,哪些代码会被回滚?

会回滚从生效的@Transactional下面的所有内容,包含try catch内容

四、示例

示例一
@Transactional
public void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}// 异常代码System.out.println("".substring(4));
}@Transactional
public void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);
}
结果是,test31的正常代码和test32的正常代码回滚。这里的test31的@Transactional有效,执行异常代码时,会回滚test31里面包含的所有内容,包括try catch里面的test32的内容

示例二
public void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}
}@Transactional
public void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);// 异常代码System.out.println("".substring(4));
}

结果是,test31的正常代码,执行成功,test32的正常代码被回滚

示例三,文章开头的例子
public class TestService {@Autowiredprivate TestService service;@Transactionalpublic void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}}@Transactionalpublic void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);// 异常代码System.out.println("".substring(4));}
}

结果是,test31的正常代码执行成功,test32的正常代码也执行成功。这里容易混淆,因为test31的@Transactional生效,但是并没有抓到异常,而是被catch住了,故当执行test32异常时,并不会回滚test32执行成功的代码。

像test32的@Transactional是无效的这种代码,在项目中也比较常见,比如某些方法被其他方法复用时。

总结
        1、确保注解生效

        2、代码异常被生效的注解抓到时,才会回滚

        3、回滚时,会回滚注解下面的所有内容


注:@DSTransactional用法一样

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

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

相关文章

提升测试工具开发的思考

本文针对测试部效率提升测试工具开发、管理、维护暴露出来的问题的一些思考以及一些个人改进观点。 写在前面 本文提到的效率提升测试工具不是指的部门中固有的自动化测试工具,这里提到的测试工具统一指测试人员在工作之余自主开发用于期望替代重复、繁琐、耗时的手…

数据库_mongoDB

1 介绍 MongoDB 是一种 NoSQL 数据库,它将每个数据存储为一个文档,这里的文档类似于 JSON/BSON 对象,具体数据结构由键值(key/value)对组成。字段值可以包含其他文档,数组及文档数组。其数据结构非常松散&…

Redis 数据结构:高频面试题及解析

概述 Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。 键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。 Redis 支持很多特性&…

Nature 确认:大语言模型只是没有感情的「学人精」

DeepMind、EleutherAI 科学家提出,大模型只是在角色扮演。 ChatGPT 爆火后,大语言模型一跃而至,成为了行业与资本的宠儿。而在人们或是猎奇、或是探究地一次次对话中,大语言模型所表现出的过度拟人化也引起了越来越多的关注。 其实…

【DEBUG】AttributeError: module ‘numpy‘ has no attribute ‘object‘

error File “numpy/init.py”, line 305, in getattr AttributeError: module ‘numpy’ has no attribute ‘object’. np.object was a deprecated alias for the builtin object. To avoid this error in existing code, use object by itself. Doing this will not modif…

【数据结构】哈希经典应用:布隆过滤器(哈希+位图)——[深度解析](9)

前言 大家好吖,欢迎来到 YY 滴 数据结构 系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 主要内容含: 欢迎订阅 YY滴 数据结构 专栏!更多干货持续更新!以下是传送门! 目录 一.布隆过滤器产生的…

第31期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大型语言模型(LLM)等安全领域应用的知识。在这里,您可以…

Plasmocin® Treatment (ant-mpt)可用于干细胞支原体污染清除

Plasmocin™作为Invivogen的支原体抗生素产品之一,受国内外许多科研工作者使用并大力推广。其包含大环内酯物及对苯二酚两种主要成分,可有效作用于支原体复制的蛋白合成阶段和DNA复制阶段,只需两周即可清除支原体污染,并且不会影响…

【CANoe】CANoe手动发送XCP报文读取观测量

文章目录 1、硬件连接:配置CANoe的CAN端口,连接到ECU标定对应的CAN口2、配置CAN IG模块报文:连接XCP,读取观测量,断开XCP3、报文解析4、参考资料 1、硬件连接:配置CANoe的CAN端口,连接到ECU标定…

文本生成图片 学习笔记

目录 diffusion-v1-5 修改参数sample_size: diffusion-v1-5 安装: pip install diffusers 模型下载地址: 深入浅出完整解析Stable Diffusion(SD)核心基础知识 - 知乎 from diffusers import StableDiffusionPipeline import torchmodel_id = "./stable-diffus…

构筑安全之城:迅软DSE助力大型建筑企业打造数据防泄密方案

电子文件如今已成为各大建筑机构和设计院进行信息存储的主要方式,以及信息交换的重要载体。而对于如何保护好单位内的设计图纸、工程方案等重要资料的数据防泄密问题,就需要相关单位规划好一套合规有效的数据防泄密解决方案。 企业简介 该企业是我国最早…

压缩pdf怎么压缩又小又清晰?超级实用!

当PDF文件过大时,很容易遇到无法上传等现象,这时候我们可以借助一些专业的压缩工具,将PDF文件压缩变小,如果你还不知道怎么做,下面就来看下具体的压缩方法吧。 方法一:使用嗨格式压缩大师 1、打开电脑上安…

Leetcode 78 子集

题意理解: 求一个集合的所有子集。该集合中没有重复元素。 首先明确什么是子集:子集中的元素都在全集里。 [1,2,3] 子集:[]、[1]、[2]、[3]、[12]、[13]、[23]、[123] 注意:[]空集是所有集合的子集。 解题思路: 类似于…

【obs】官方最强插件obs-websocket入门

▒ 目录 ▒ 🛫 导读需求开发环境 1️⃣ obs-websocket简介OBS版本说明obs-websocket版本说明安装(27.x版本OBS)配置插件 2️⃣ OBS-web介绍特征使用方法-5.xhttp vs https 3️⃣ obs-websocket-js开发tester.html 4️⃣ 其它开源项目obs-stud…

vue2-使用vue-i18n搭建多语言切换环境

安装 注意:vue2.0要用8版本的,使用9版本的会报错 npm install vue-i18n8.27.0 --save 创建相关的语言包文件 在src目录下,新建i18n文件夹 在新文件夹i18n中新建langs文件夹,里边放语言文本文件.js zh.js:存…

vmware 使用scsi_id 获取ID返回空

/usr/lib/udev/scsi_id -g -u -d --whitelisted --replace-whitespace --device/dev/sdb2 结果返回是空的,根本的原因是 虚拟机的设置问题。 修改虚拟机的配置文件,vmx后缀的那个:例如 CentOS 7 64 位.vmx disk.EnableUUID "TRUE&quo…

ADC学习总结

ADC的架构分类: 1、Delta-Sigma 采样率一般是在1M以内,位数一般可以做的很高,比如24位,Delta-Sigma ADC采用了过采样技术,不需要在模拟输入端加抗混叠滤波,由后端数字滤波器进行处理,通过信噪…

Yearning安装及使用

Yearning是基于go和vue开发的一款SQL审核工具。在实际开发中,生产环境DDL、DML脚本一般需要走工单流程进行审批后执行,Yearning可以制定MySQL的SQL审核流程、规范及审批等功能。 一、主要功能 1.支持自定义SQL审核流程2.自动化SQL语句审核,可对SQL进行…

springboot(ssm北工国际健身俱乐部 健身管理系统Java系统

springboot(ssm北工国际健身俱乐部 健身管理系统Java系统 开发语言:Java 框架:ssm/springboot vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.7(或8.0) …

什么是高阶组件

高阶组件(HOC)是一个将组件作为参数并返回一个新组件的函数。他是一种由 React 自身组合性质产生的模式。由于高阶组件接受他的组件参数来动态创建子组件,且不会修改或复制其组件中的任何行为,因此他与纯组件较为类似。 高阶组件可…