@Transactional 事务注解
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class)
简单解析:如果有事务,那么加入事务,没有的话新建一个; 串行化最高级隔离级别; 遇到异常回滚。

@Transactional之value
value这里主要用来指定不同的事务管理器;主要用来满足在同一个系统中,存在不同的事务管理器。比如在Spring中,声明了两种事务管理器txManager1, txManager2.
然后,用户可以根据这个参数来根据需要指定特定的txManager.
@Transactional之propagation(service中调用其他service时需要注意)
| @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没有声明事务,那就 |
Propagation支持7种不同的传播机制:
- REQUIRED
业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就加入该事务,否则自己创建一个新的事务.这是spring默认的传播行为.。
- SUPPORTS:
如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分,如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。
- MANDATORY:
只能在一个已存在事务中执行,业务方法不能发起自己的事务,如果业务方法在没有事务的环境下调用,就抛异常
- REQUIRES_NEW
业务方法总是会为自己发起一个新的事务,如果方法已运行在一个事务中,则原有事务被挂起,新的事务被创建,直到方法结束,新事务才结束,原先的事务才会恢复执行.
- NOT_SUPPORTED
声明方法需要事务,如果方法没有关联到一个事务,容器不会为它开启事务.如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行.
- NEVER:
声明方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常.只有没关联到事务,才正常执行.
- NESTED:
如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效.
其实大家最感到困惑的是REQUIRED_NEW和NESTED两种不同的传播机制,功能类似,都涉及到了事务嵌套的问题,那两者有何区别呢?该如何正确使用这两种模式呢?
| @Transactional(isolation = Isolation.READ_UNCOMMITTED) | 读取未提交数据(会出现脏读, 不可重复读) 基本不使用 |
| @Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER默认) | 读取已提交数据(会出现不可重复读和幻读) |
| @Transactional(isolation = Isolation.REPEATABLE_READ) | 可重复读(会出现幻读) |
| @Transactional(isolation = Isolation.SERIALIZABLE) | 串行化 |
隔离级别所要解决的问题是在应用程序中,存在多个事务同时在运行之时,需要解决和处理好的问题。那首先来看看,一般会出现哪些问题呢?先来看看吧。
- 脏读(dirty read)
一个事物更新了数据库中的某些数据,另一个事物读取了这些数据,这时前一个事物由于某些原因回滚了,那么第二个事物读取的数据就是“脏数据”
- 不可重复读(non-repeatable read)
一个事物需要两次查询同一数据,但两次查询中间可能有另外一个事物更改了这个数据,导致前一个事物两次读出的数据不一致。
- 幻读 (phantom read)
一个事物两次查询同一个表,但两次查询中间可能有另外一个事物又向这个表中插入了一些新数据,导致前一个事物的两次查询不一致
下面来看看Spring中@Transactional中Isolation有具备的值:
- DEFAULT 使用各个数据库默认的隔离级别
- Read Uncommited :读未提交数据( 会出现脏读,不可重复读,幻读 )
- Read Commited :读已提交的数据(会出现不可重复读,幻读)
- Repeatable Read :可重复读(会出现幻读)
- Serializable :串行化
@Transactional之timeout
用于设置事务处理的时间长度,阻止可能出现的长时间的阻塞系统或者占用系统资源。单位为秒。如果超时设置事务回滚,并抛出TransactionTimedOutException异常。
Spring事务超时 = 事务开始时到最后一个Statement创建时时间 + 最后一个Statement的执行时超时时间(即其queryTimeout)。
关于事务超时时间的计算可以参考:http://jinnianshilongnian.iteye.com/blog/1986023
@Transactional之readOnly
默认情况下是false,可以显示指定为true, 告诉程序该方法下使用的是只读操作,如果进行其他非读操作,则会跑出异常;这个紧紧适用于只有readOnly标识的情况下,当其与propagation机制同时使用之时,则会出现只读设置被覆盖的情况,比如在required的情况下。在使用 REQUIRED 传播模式时,会抛出一个只读连接异常。使用 JDBC 时是这样。使用基于 ORM 的框架时,只读标志只是对数据库的一个提示,并且一条基于 ORM 框架的指令(本例中是 hibernate)将对象缓存的 flush 模式设置为 NEVER,表示在这个工作单元中,该对象缓存不应与数据库同步。不过,REQUIRED 传播模式会覆盖所有这些内容,允许事务启动并工作,就好像没有设置只读标志一样。
具体的详细内容可以参考: http://robinsoncrusoe.iteye.com/blog/825531
@Transactional之rollbackForClassName/rollbackFor
Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked,如果遇到checked意外就不回滚。
用来指明回滚的条件是哪些异常类或者异常类名。用法比较简单,这些不再赘述。
@Transactional之noRollbackForClassName/noRollbackFor
作用雷同于8, 用来指明在抛出特定异常的情况下,不进行数据库的事务回滚操作。
- spring事务回滚规则
- @Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
- 用 spring 事务管理器,由spring来负责数据库的打开,提交,回滚。默认遇到运行期异常(throw new RuntimeException("注释");)会回滚,即遇到不受检查(unchecked)的异常时回滚;而遇到需要捕获的异常(throw new Exception("注释");)不会回滚,即遇到受检查的异常(就是非运行时抛出的异常,编译器会检查到的异常叫受检查异常或说受检查异常)时,需我们指定方式来让事务回滚 要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception。class,其它异常}) 。
- @Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 <tx:annotation-driven/>元素的出现 开启了事务行为。
- Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。
- @Transactional 注解标识的方法,处理过程尽量的简单。尤其是带锁的事务方法,能不放在事务里面的最好不要放在事务里面。可以将常规的数据库查询操作放在事务前面进行,而事务内进行增、删、改、加锁查询等操作。
- @Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。
@Transactional 事务注解的更多相关文章
- Spring提取@Transactional事务注解的源码解析
声明:本文是自己在学习spring注解事务处理源代码时所留下的笔记: 难免有错误,敬请读者谅解!!! 1.事务注解标签 <tx:annotation-driven /> 2.tx 命名空间 ...
- Spring中的@Transactional事务注解
事务注解方式 @Transactional 当标于类前时, 标示类中所有方法都进行事物处理 , 例子: @Transactional public class TestServiceBean impl ...
- spring @Transactional 事务注解
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE, rollbackFor = ...
- spring @Transactional 事务注解的坑
1. 在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上. 2. @Transactiona ...
- JPA的事务注解@Transactional使用总结
在项目开发过程中,如果您的项目中使用了Spring的@Transactional注解,有时候会出现一些奇怪的问题,例如: 明明抛了异常却不回滚? 嵌套事务执行报错? ...等等 很多的问题都是没有全面 ...
- Spring学习之事务注解@Transactional
今天学习spring中的事务注解,在学习Spring注解事务之前需要明白一些事务的基本概念: 事务:并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通 ...
- 《四 spring源码》spring的事务注解@Transactional 原理分析
先了解什么是注解 注解 Jdk1.5新增新技术,注解.很多框架为了简化代码,都会提供有些注解.可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件. 注解不会也不能影 ...
- Spring事务管理者与Spring事务注解--声明式事务
1.在Spring的applicationContext.xml中配置事务管理者 PS:具体的说明请看代码中的注释 Xml代码: <!-- 声明式事务管理的配置 --> <!-- 添 ...
- spring事务注解
@Transactional只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能. Spring使用声明式事务处理,默认 ...
随机推荐
- ERROR in xxxx.js from UglifyJS——配置版本混杂版
常规解决套路可以参考这篇:https://segmentfault.com/a/11... 我采用了上面的做法,依然没法解决.我采用的是vue-cli脚手架自动生成的项目结构: vue-cli版本 2 ...
- 改造vue-quill-editor: 结合element-ui上传图片到服务器
前排提示:现在可以直接使用封装好的插件vue-quill-editor-upload 需求概述 vue-quill-editor是我们再使用vue框架的时候常用的一个富文本编辑器,在进行富文本编辑的时 ...
- java 实现顺序结构线性列表
package com.ncu.list; /** * * 顺序结构线性列表 * * @author liuhao * */ public class SquenceList<T> { p ...
- Maven学习总结(22)——Maven常用插件介绍
我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的.进一步说,每个任务对应 ...
- c++_benchMark_vector_list_deque
title: c++_benchMark_vector_list_deque date: 2015-08-01 22:32:39 作者:titer1 + ZhangYu 出处:www.drysalte ...
- C++ Primer笔记13_运算符重载_总结
总结: 1.不能重载的运算符: . 和 .* 和 ?: 和 :: 和 sizeof 和 typeid 2.重载运算符有两种基本选择: 类的成员函数或者友元函数, 建议规则例如以下: 运算符 建议使用 ...
- hibernate ID生成策略配置
1.Student.hbm.xml配置 <hibernate-mapping package="com.wxh.hibernate.model"> <class ...
- UNIX环境高级编程之第4章:文件和文件夹-习题
4.1 stat函数是尾随符号链接的,所以用stat替换lstat不会显示符号链接的信息 4.2 在一个目录下先再shell中输入umask shell进程再进行创建文件的操作.其权限抖都会被屏蔽 4 ...
- UTF8有很明显的特征:如果最高字节为0,则表示一个英文字符(与ASCII完全相同)。如果有2个以上1,表示是首个字节。如果最高位是10,则表示一个中间字节。
摘自<Qt中的C++技术.pdf> page 33
- java9新特性-6-多版本兼容jar包
1.官方Feature 238: Multi-Release JAR Files 2.使用说明 当一个新版本的Java出现的时候,你的库用户要花费数年时间才会切换到这个新的版本.这就意味着库得去向后兼 ...