Spring Boot事务管理(中)
在上一篇 Spring Boot事务管理(上)的基础上介绍Spring Boot事务属性和事务回滚规则 。
4 Spring Boot事务属性
什么是事务属性呢?事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了5个方面,如图所示,它们定义于TransactionDefinition接口类

1、 事务隔离级别
隔离级别是指若干个并发事务之间的隔离程度。
Spring Boot的隔离级别被封装在枚举类Isolation,枚举值取自接口TransactionDefinition 定义,该接口中定义了五个表示隔离级别的常量:
|
隔离级别 |
含义 |
|
ISOLATION_DEFAULT |
默认值,使用后端数据库默认的隔离级别 |
|
ISOLATION_READ_UNCOMMITTED |
表示一个事务可以读取另一个事务修改但还没有提交的数据。可能导致脏读,不可重复读和幻读,因此很少使用该隔离级别。最低的隔离级别。 |
|
ISOLATION_READ_COMMITTED |
表示一个事务只能读取另一个事务已经提交的数据。可以防止脏读,但是幻读或不可重复读仍有可能发生,这也是大多数情况下的推荐值。 |
|
ISOLATION_REPEATABLE_READ |
表示一个事务在整个过程中可以多次重复执行某个查询并且每次返回的记录都相同。可以防止脏读和不可重复读,但幻读仍有可能发生。MySQL默认隔离级别。 |
|
ISOLATION_SERIALIZABLE |
所有的事务依次逐个执行,事务之间完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能,因为它通常是通过完全锁定事务相关的数据库表来实现的。 |
2、 事务传播规则
事务传播行为(propagation behavior)用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时候,事务如何传播。
传播行为定义了事务范围,何时触发事务,是否暂停现有事务,或者在调用方法是如果没有事务则失败等等。
Spring Boot的事务传播行为常量被封装在枚举类Propagation,枚举值取自接口TransactionDefinition,在接口中定义了如下七个表示传播行为的常量:
|
传播行为 |
含义 |
|
PROPAGATION_REQUIRED |
如果当前存在事务,则加入该事务;否则,新建一个事务。这是默认值 |
|
PROPAGATION_REQUIRES_NEW |
新建事务,如果当前存在事务,则挂起当前事务 |
|
PROPAGATION_SUPPORTS |
如果当前存在事务,则加入该事务;否则,以非事务的方式继续运行 |
|
PROPAGATION_NOT_SUPPORTED |
以非事务方式运行,如果当前存在事务,则挂起当前事务 |
|
PROPAGATION_NEVER |
以非事务方式运行,如果当前存在事务,则抛异常 |
|
PROPAGATION_MANDATORY |
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常 |
|
PROPAGATION_NESTED |
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED |
下面贴出TransactionDefinition中关于传播行为的源码。
/**
* Support a current transaction; create a new one if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p>This is typically the default setting of a transaction definition,
* and typically defines a transaction synchronization scope.
*/
int PROPAGATION_REQUIRED = 0; /**
* Support a current transaction; execute non-transactionally if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> For transaction managers with transaction synchronization,
* {@code PROPAGATION_SUPPORTS} is slightly different from no transaction
* at all, as it defines a transaction scope that synchronization might apply to.
* As a consequence, the same resources (a JDBC {@code Connection}, a
* Hibernate {@code Session}, etc) will be shared for the entire specified
* scope. Note that the exact behavior depends on the actual synchronization
* configuration of the transaction manager!
* <p>In general, use {@code PROPAGATION_SUPPORTS} with care! In particular, do
* not rely on {@code PROPAGATION_REQUIRED} or {@code PROPAGATION_REQUIRES_NEW}
* <i>within</i> a {@code PROPAGATION_SUPPORTS} scope (which may lead to
* synchronization conflicts at runtime). If such nesting is unavoidable, make sure
* to configure your transaction manager appropriately (typically switching to
* "synchronization on actual transaction").
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
*/
int PROPAGATION_SUPPORTS = 1; /**
* Support a current transaction; throw an exception if no current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization within a {@code PROPAGATION_MANDATORY}
* scope will always be driven by the surrounding transaction.
*/
int PROPAGATION_MANDATORY = 2; /**
* Create a new transaction, suspending the current transaction if one exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Java EE).
* <p>A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
* transaction synchronizations. Existing synchronizations will be suspended
* and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_REQUIRES_NEW = 3; /**
* Do not support a current transaction; rather always execute non-transactionally.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Java EE).
* <p>Note that transaction synchronization is <i>not</i> available within a
* {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
* will be suspended and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_NOT_SUPPORTED = 4; /**
* Do not support a current transaction; throw an exception if a current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization is <i>not</i> available within a
* {@code PROPAGATION_NEVER} scope.
*/
int PROPAGATION_NEVER = 5; /**
* Execute within a nested transaction if a current transaction exists,
* behave like {@link #PROPAGATION_REQUIRED} else. There is no analogous
* feature in EJB.
* <p><b>NOTE:</b> Actual creation of a nested transaction will only work on
* specific transaction managers. Out of the box, this only applies to the JDBC
* {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
* when working on a JDBC 3.0 driver. Some JTA providers might support
* nested transactions as well.
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
*/
int PROPAGATION_NESTED = 6;
理解PROPAGATION_NESTED的关键是savepoint。他与REQUIRES_NEW的区别REQUIRES_NEW另起一个事务,将会与它的父事务相互独立,而Nested的事务和父事务是相依的,它的提交是要等待和父事务一块提交的。也就是说,如果父事务最后回滚,它也要回滚的;如果子事务回滚而且异常被捕获,父事务无感知,则父事务不回滚。
public class TransactionalDemo {
@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRES_NEW)
public void doSth() {
// do something
}
}
3、 事务超时
所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。
默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。
/**
* Return the transaction timeout.
* <p>Must return a number of seconds, or {@link #TIMEOUT_DEFAULT}.
* <p>Only makes sense in combination with {@link #PROPAGATION_REQUIRED}
* or {@link #PROPAGATION_REQUIRES_NEW}.
* <p>Note that a transaction manager that does not support timeouts will throw
* an exception when given any other timeout than {@link #TIMEOUT_DEFAULT}.
* @return the transaction timeout
*/
int getTimeout();
4、 事务只读属性
只读事务用于只读取但不修改数据的情形,只读事务用于特定情景下的优化,比如使用Hibernate的时候。默认为读写事务。
//@return {@code true} if the transaction is to be optimized as read-only
boolean isReadOnly();
5、 事务回滚规则
指示Spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。Spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。默认配置下,Spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。可以明确的配置在抛出哪些异常时回滚事务,包括checked异常。也可以明确定义哪些异常抛出时不回滚事务。还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。
Spring的事务边界是在调用业务方法之前开始的,通过调用connection.setAutoCommit(false)激活事务,业务方法执行完毕之后来执行commit or rollback(Spring默认取决于是否抛出runtime异常)以结束事务。如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception;否则,Spring会将你的操作commit,这样就会产生脏数据,所以你的catch代码是画蛇添足。如:
try {
// bisiness logic code
} catch(Exception e) {
// handle the exception
}
由此可以推知,在Spring中如果某个业务方法被一个try catch整个包裹起来,那么这个业务方法也就等于脱离了Spring事务的管理,因为没有任何异常会从业务方法中抛出!全被捕获并吞掉,导致Spring异常抛出触发事务回滚策略失效。不过,如果在catch代码块中采用页面硬编码的方式使事务显式的回滚,这样写也未尝不可。
预知后事如何,请听下回分解——Spring Boot事务管理(下)
Spring Boot事务管理(中)的更多相关文章
- Spring Boot事务管理(上)
摘要 本文主要介绍基于Spring Boot的事务管理,尤其是@Transactional注解详细用法.首先,简要介绍Spring Boot中如何开启事务管理:其次,介绍在Spring,Spring ...
- Spring Boot事务管理(下)
在上两篇 Spring Boot事务管理(上)和Spring Boot事务管理(中)的基础上介绍注解@Transactional. 5 @Transactional属性 属性 类型 描述 value ...
- 【Spring Boot学习之四】Spring Boot事务管理
环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 一.springboot整合事务事务分类:编程事务.声明事务(XML.注解),推荐使用注解方式,springboot默 ...
- spring boot事务管理
spring boot集成事务十分的简单,只需要在启动类上面增加@EnableTransactionManagement注解,然后在需要实现事务的方法上添加@Transactional注解就可以了.下 ...
- Java框架spring Boot学习笔记(六):Spring Boot事务管理
SpringBoot和Java框架spring 学习笔记(十九):事务管理(注解管理)所讲的类似,使用@Transactional注解便可以轻松实现事务管理.
- Spring系列.事务管理
Spring提供了一致的事务管理抽象.这个抽象是Spring最重要的抽象之一, 它有如下的优点: 为不同的事务API提供一致的编程模型,如JTA.JDBC.Hibernate和MyBatis数据库层 ...
- Spring的事务管理
事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...
- spring笔记--事务管理之声明式事务
事务简介: 事务管理是企业级应用开发中必不可少的技术,主要用来确保数据的完整性和一致性, 事务:就是一系列动作,它们被当作一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. Spring中使 ...
- Spring应用——事务管理
事务基础:请参看:http://www.cnblogs.com/solverpeng/p/5720306.html 一.Spring 事务管理 1.前提:事务管理器 在使用 Spring 声明式事务管 ...
随机推荐
- Spark 精品文章转载(目录)
学习 Spark 中,别人整理不错的文章,转载至本博客,方便自己学习,并按照不同的模块归档整理.每个文章作者能力不同,写文章所处的时间点不同,可能会略有差异,在阅读的同时,注意当时的文章的内容是否已经 ...
- Linux服务器CPU使用率较低但负载较高
CPU使用率较低但负载较高 问题描述 Linux 系统没有业务程序运行,通过 top 观察,类似如下图所示,CPU 很空闲,但是 load average 却非常高,如下图所示. 处理办法 load ...
- 猿题库从 Objective-C 到 Swift 的迁移
猿题库从 Objective-C 到 Swift 的迁移 引言 相信没有人会怀疑,Swift 是 iOS 开发未来的主流语言,但是由于 Swift 语言的不断变化以及庞大的迁移成本,真正把项目迁移到 ...
- [转]客户端js判断文件类型和文件大小即限制上传大小
原文地址:https://www.jb51.net/article/43498.htm 需要脚本在客户端判断大小和文件类型,由于网上没有适合的,就自己写了一个并测试 文件上传大小限制的一个例子,在此与 ...
- Groovy 和 Gradle
0.Groovy和Gradle是什么关系? Gradle,自动化构建工具,通过简单编写Groovy脚本,便可进行依赖管理并完成项目构建: 1. Groovy有什么用? 脚本+Java代码: 2. Gr ...
- Nginx+Keepalived+Tomcat高可用负载均衡,Zookeeper集群配置,Mysql(MariaDB)搭建,Redis安装,FTP配置
JDK 安装步骤 下载 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html rpm ...
- Iterator和ListIterator
Iterator和ListIterator主要区别有: 一.ListIterator有add()方法,可以向List中添加对象,而Iterator不能. 二.ListIterator和Iterator ...
- Window应急响应(五):ARP病毒
0x00 前言 ARP病毒并不是某一种病毒的名称,而是对利用arp协议的漏洞进行传播的一类病毒的总称,目前在局域网中较为常见.发作的时候会向全网发送伪造的ARP数据包,严重干扰全网的正常运行,其危害甚 ...
- Aspose.Words使用技巧
咨询个问题啊,我在使用aspose生成word,遇到了两个问题,一个是用aspose自动生成的目录的字体与标题的字体一致,但是用户不想他们一致,如何修改:二是,用户只想在正文部分显示页码,目录等页面不 ...
- 如何免费下载付费音乐歌曲,6个网站+8个APP
现在听音乐的软件,QQ音乐,酷狗,网易云等,很多歌曲可以在线听. 但是下载某些歌曲或者在线听高品质无损的都需要付费. 这一期,给大家推荐的是免费下载付费歌曲工具,包括网站跟APP. 网站篇 1.VIP ...