当前位置: 首页 > news >正文

Spring @Transactional 事务注解

一、spring 事务注解

1、实现层(方法上加)

import org.springframework.transaction.annotation.Transactional;@Transactional(rollbackFor = Exception.class)public JsonResult getRtransactional() {// 手动标记事务回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}

二、事务特性

1、@Transactional注解是用于事务控制的

需要知道事务的 ACID 特征:

  • 原子性(Atomicity,或称不可分割性)
  • 一致性(Consistency)
  • 隔离性(Isolation,又称独立性)
  • 持久性(Durability)

事务是用来控制数据的 ACID 特性的,用于保证数据的正确性和完整性。

2、@Transactional 注解有两种使用方式:

  • 标注在类上面:当作用于类上时,该类的所有public方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
  • 标注在方法上面:当作用于方法上时,只有当该方法发生了异常才会进行回滚,其他的方法不受影响。

在项目中使用,@Transactional(rollbackFor=Exception.class),如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚。

三、事务传播行为与隔离级别

@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

1、事物传播行为介绍:

2、事物超时设置:

@Transactional(timeout=30) //默认是30秒

3、事务隔离级别:

// 读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_UNCOMMITTED)// 读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.READ_COMMITTED)// 可重复读(会出现幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)// 串行化
@Transactional(isolation = Isolation.SERIALIZABLE):// MYSQL: 默认为REPEATABLE_READ 可重复读 级别
// SQLSERVER: 默认为READ_COMMITTED 读取已提交数据  

脏读 : 一个事务读取到另一事务未提交的更新数据。

不可重复读 : 在同一事务中,多次读取同一数据返回的结果有所不同,即后续读取可能读到另一事务已提交的更新数据, 相反,

可重复读:在同一事务中多次读取数据时能够保证所读数据一样,即后续读取不能读到另一事务已提交的更新数据。

幻读 : 一个事务读到另一个事务已提交的insert数据。

四、spring支持 编程式事务管理 和 声明式事务管理 两种方式

1、编程式事务管理使用 TransactionTemplate 或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring 推荐使用 TransactionTemplate。

2、声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务管理也有两种常用的方式:一种是基于tx和aop名字空间的xml配置文件;另一种是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

使用注解形式的方式使用事务需要在xml配置文件中配置如下信息

<!-- 服务事务管理 -->
<bean id="demoTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="demoDataSource"/>
</bean><!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="demoTransactionManager"/>

五、需要注意的几点如下

1、@Transactional 注解只能被应用到public方法上,对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能。

2、用 spring 事务管理器,由 spring 来负责数据库的打开、提交、回滚,默认遇到运行期异常(throw new RuntimeException("注释");)会回滚,即遇到不受检查(unchecked)的异常时执行回滚;而遇到需要捕获的异常(throw new Exception("注释");)不会回滚,即遇到受检查的异常(就是非运行时抛出的异常,编译器会检查到的异常叫受检异常)时,需要我们指定方式来让事务回滚。如果要想所有异常都回滚,则要加上@Transactional( rollbackFor=Exception.class),
如果让unchecked异常不回滚: @Transactional(notRollbackFor=RunTimeException.class)。如下代码所示:

@Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚
public void methodName() {throw new Exception("注释");
}
@Transactional(noRollbackFor=Exception.class)//指定不回滚,遇到运行期例外(throw new RuntimeException("注释");)会回滚
public ItimDaoImpl getItemDaoImpl() {throw new RuntimeException("注释");
}

3、@Transactional 注解应该只被应用到public可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不具有事务功能。

4、@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅是一种元数据,能够被可以识别。上面的例子中,其实正是元素的出现开启了事务行为。也就是说要有具体的 bean 出现时事务才会起作用。

5、Spring 团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别。因此,请接受 Spring 团队的建议,必须接受啊!

六、@Transactional注解所具有的属性

七、事务可能导致锁表

事务有可能导致锁表,从而导致查询操作超时。锁表的原因是多个事务同时操作某一张表。

mysql事务锁表参考博文:MySQL 死锁-CSDN博客

(mysql事务锁表导致查询超时)

mysql中主要是注意以下三张表:

select * from information_schema.INNODB_LOCKS;
select  * from information_schema.INNODB_LOCK_WAITS;
select * from information_schema.INNODB_TRX;

相关文章:

  • SQL入门教程
  • 提高篇(八):扩展Processing功能:从库使用到跨平台应用
  • 鸿蒙开发接口数据管理:【@ohos.data.distributedDataObject (分布式数据对象)】
  • 总结开发过程遇到问题有哪些渠道可以寻找解决方案
  • 遗址博物馆ar互动展示软件提供丰富的趣味化体验
  • springboot编写简述01
  • linux的编辑安装
  • 基于JSP技术的社区疫情防控管理信息系统
  • 车载开发之预置无源码apk到Android系统(带so文件)
  • 【JavaScript】【分享】关于this
  • CSS实现一个雨滴滑落效果
  • 新奇css模板
  • Java/Golang:活用interface,增加程序扩展性
  • 堆和栈的空间利用率
  • 2024下《系统集成项目管理工程师》50个高频考点汇总!值得收藏
  • 0x05 Python数据分析,Anaconda八斩刀
  • HTML5新特性总结
  • Intervention/image 图片处理扩展包的安装和使用
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • 排序算法之--选择排序
  • 深入浅出webpack学习(1)--核心概念
  • 什么是Javascript函数节流?
  • 思否第一天
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • #includecmath
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • (C++17) optional的使用
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (LeetCode C++)盛最多水的容器
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (转)Linq学习笔记
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (转载)Google Chrome调试JS
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .Net IOC框架入门之一 Unity
  • .net8.0与halcon编程环境构建
  • /etc/shadow字段详解
  • @EnableWebMvc介绍和使用详细demo
  • [AIGC] Redis基础命令集详细介绍
  • [ai笔记3] ai春晚观后感-谈谈ai与艺术
  • [C#]C# winform实现imagecaption图像生成描述图文描述生成
  • [C++]类和对象【上篇】
  • [GDMEC-无人机遥感研究小组]无人机遥感小组-000-数据集制备
  • [IE 技巧] 显示/隐藏IE 的菜单/工具栏
  • [JavaWeb]——过滤器filter与拦截器Interceptor的使用、执行过程、区别
  • [LeetBook]【学习日记】获取子字符串 + 颠倒子字符串顺序
  • [redis] Jedis 与 ShardedJedis 设计
  • [tarjan][hdu 1269]
  • [UE4]射中机器人
  • [翻译]WP7 QuickStart-第八篇-屏幕方向