首页 > 编程语言 >【java】@Transactional事务注解

【java】@Transactional事务注解

时间:2024-05-12 09:12:34浏览次数:28  
标签:回滚 java Propagation Transactional 事务 propagation 注解

事务注解目录
一、什么是事务?
二、事务的特性 (具有ACID的特性)
1. A 原子性(atomicity) :
2. C 一致性(consistency):
3. I 隔离性(isolation):
4. D 持久性(Durability):
三、@Transactional的介绍
四、@Transactional的实现原理
五、@Transactional事务的隔离级别
六、@Transactional事务的传播机制
七、@Transactional事务的属性
八、失效场景
@Transactional 是java中使用的注解形式的事务

既然使用@Transactional就要理解什么是事务。下面将会详细介绍:

一、什么是事务?
事务(Transactional) 就是把多个要做的操作组合成一个整体,利用事务的特性来保证操作的安全性,如果一个事务做到一半出现任何错误,就会进行回滚操作,来恢复成最初的模样。

二、事务的特性 (具有ACID的特性)
1. A 原子性(atomicity) :
事务是一个不可分割的工作单位,事务中的操作要么都修改,要么都不修改。

2. C 一致性(consistency):
事务在完成时,必须是所有的数据都保持一致状态。

3. I 隔离性(isolation):
一个事务的执行不能被其他事务所影响。

4. D 持久性(Durability):
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的.

三、@Transactional的介绍
@Transactional 是java中使用的注解形式的事务,也就是说可以直接使用该注解来完成事务操作.

使用的位置: 该注解可以写在类或者方法上面.注意不能写在接口上。


方法的权限: 必须是public的方法才可以使用该注解.

默认情况下,事务遇到RuntimeException 时会回滚 . 遇到受检查的异常 是不会回滚的. 要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常})


四、@Transactional的实现原理
该注解是通过JDBC的事务 + Spring的AOP动态代理来完成的.
基于AOP面向切面的,它将具体业务与事务处理部分解耦,代码侵入性很低

事务开始时,通过AOP机制,生成一个代理connection对象,

并将其放入 DataSource 实例的某个与 DataSourceTransactionManager 相关的某处容器中。

在接下来的整个事务中,客户代码都应该使用该 connection 连接数据库,

执行所有数据库命令。

事务结束时,回滚在第1步骤中得到的代理 connection 对象上执行的数据库命令,

然后关闭该代理 connection 对象

五、@Transactional事务的隔离级别
隔离级别类似于(Exception, error)这种, 不同的级别,安全性不同.

如果对(脏读,幻读,不可重复读)这些不太懂的话,建议学习一下Mysql隔离级别的相关知识.

@Transactional(isolation = Isolation.READ_UNCOMMITTED):读取未提交数据(会出现脏读,不可重复读) 基本不使用

@Transactional(isolation = Isolation.READ_COMMITTED):读取已提交数据(会出现不可重复读和幻读)

@Transactional(isolation = Isolation.REPEATABLE_READ):可重复读(会出现幻读)

@Transactional(isolation = Isolation.SERIALIZABLE):串行化

六、@Transactional事务的传播机制
事务的传播机制,就是代表事务在不同场景下所要做的操作. 比如(当前事务中又嵌套了另一个事务,这个时候是选择重新开启一个事务,还是使用原来的事务).

@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不为这个方法开启事务

@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务

@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常

@Transactional(propagation=Propagation.NEVER)
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)

@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

七、@Transactional事务的属性
属性 类型 描述
value String 可选的限定描述符,指定使用的事务管理器
propagation enum: Propagation 可选的事务传播行为设置
isolation enum: Isolation 可选的事务隔离级别设置
readOnly boolean 读写或只读事务,默认读写
timeout int (in seconds granularity) 事务超时时间设置
rollbackFor Class对象数组,必须继承自Throwable 导致事务回滚的异常类数组
rollbackForClassName 类名数组,必须继承自Throwable 导致事务回滚的异常类名字数组
noRollbackFor Class对象数组,必须继承自Throwable 不会导致事务回滚的异常类数组
noRollbackForClassName 类名数组,必须继承自Throwable 不会导致事务回滚的异常类名字数组
详细请看我之前写的文章:@Transactional 注解参数详解

八、失效场景
应用在非 public 修饰的方法上

属性 propagation 设置错误

若是错误的配置以下三种 propagation,事务将不会发生回滚。

TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
属性 rollbackFor 设置错误
rollbackFor 可以指定能够触发事务回滚的异常类型。Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务

同一个类中方法调用,导致@Transactional失效
由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理

异常被 ”catch“导致@Transactional失效

数据库引擎不支持事务

标签:回滚,java,Propagation,Transactional,事务,propagation,注解
From: https://www.cnblogs.com/zhoading/p/18187459

相关文章

  • 如果你还不了解Java类的加载过程,来看看这一篇吧
    文章首发于【Java天堂】,跟随我探索Java进阶之路!虚拟机类加载机制在Java代码被编译成Class文件之后,最终需要加载到Java虚拟机中才能被运行和使用,Java虚拟机加载Class文件到内存,并对数据进行校验、转换、解析和初始化之后,才变成了我们真正可以使用的Java类型,这个过程就叫做Java......
  • java MySQL的in查询两个字段同时相等的多个数据查询
    在Java中想进行下面的查询,不想写循环一条条查selectid,name,address,age fromuserswherename='A' and address='addr1'selectid,name,address,age fromuserswherename='B' and address='addr2'selectid,name,address,age fromusers......
  • Java父子类方法调用
    判定首先使用“instanceof”来判定在new了某个项目后两个类型之间的父子关系调用父类或子类方法首先明确两个项目的继承关系,同时执行父让子的原则,当两者方法名重复时,优先执行子类方法。当new父类所定义的变量名要使用子类的方法时(父类中没有该方法)要用括号将子类项目名括住......
  • Java-线程-并发解决方案
    0.背景在[Java-线程-并发]这篇文章中,我们引入了并发场景下的一些问题,并在末尾给出了几种常见的解决方案。1.方案1.1synchronizedsynchronized是Java中的一个关键字,用于提供同步机制,保证多线程环境下对共享资源的安全访问。通过使用synchronized,Java虚拟机(JVM)保证同一时......
  • ETLCloud中如何执行Java Bean脚本
    ETLCloud中如何执行Java Bean脚本在ETLCloud这一强大的数据集成和转换平台中,执行Java Bean脚本的能力为其增添了更多的灵活性和扩展性。Java Bean脚本不仅仅是一段简单的代码,而是一种强大的工具,可以帮助用户定制和优化数据处理的每一个环节。为了充分利用这一功能,您需要编写......
  • JAVA开发使用@JsonFormat注解,日期比实际日期少一天问题
    前言最近同事反馈一个问题,说是日期保存后未发生变化。刚开始以为是字段未对应或者是未保存成功,当我去进行排查的时候发现,发现数据保存没有问题。奇了怪了。问题现象库里日期数据保存正确,但是后台返回前台页面发现不正确。排查过程刚开始怀疑是数据未保存成功,经过测试发现数据......
  • JAVA LIST按照指定字段去重重复
    JAVAList按照指定字段去重重复List<TalentPlanStudentEntity>studentList=relatePlanStudentList.stream() .collect(Collectors.collectingAndThen(Collectors.toCollection( ()->newTreeSet<>(Comparator.comparing(TalentPlanStudentEntity::getUserId......
  • Java-线程-并发问题和ConcurrentHashMap
    0.背景在经典八股文中,我们会背:啊,hashmap是线程不安全的,concurrentHashMap是线程安全的。然后呢,又背:啊,为啥ConcurrentHashMap是安全的,因为加锁了。好好好,接着八股:啊,啥啥分段锁。本文,结合实际例子来进行分析,这他妈的到底是在叭叭啥。一切,从一个Hashmap的demo谈起。pu......
  • JavaScript 生成32位UUID
    functionuuid(){varlen=32;//32长度varradix=16;//16进制varchars='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');varuuid=[],i;radix=radix||chars.length;if(......
  • JavaScript 原型链与继承问答(第一天)
    1、在编程语言中,什么叫语法糖在编程语言中,"语法糖"是指一种编程语言的语法功能,它并不改变语言的功能,但可以让代码更易读、更易写。它是一种语法上的简化,让程序员能够用更少的代码表达相同的逻辑。比如es6中,一个对象想复用另外一个对象的所有字段,可以这样constobj2={...obj......