Spring Framework中常见的事务传播陷阱(译文)
最近看到Medium上一篇讨论Spring Framework中事务传播的文章,解释了几种常见的问题,解释的不错,这里直接翻译吧(意译为主,粗体和斜体是我自己加上的)。
译文:
这是我的第一篇文章,我打算给大家总结一下开发者在使用Spring事务时,常常会犯的和事务传播相关的错误。
在这之前,我们先回忆一下Spring中事务是怎样传播的。
我们先看下Ken Tousen做的有关事务传播注解的笔记(译注:这里指@Transactional注解的propagation属性),这会帮助我们更清楚地记忆。
1. 私有方法
当公有方法调用私有方法时,不会创建新事务。(译注:这里有点问题,见下面评论)
@Transactional
public class MusicPlayerService { @Autowired
Song song; @Autowired
MusicCatalogueService musicCatalogueService; public void playSong() {
scrobble();
song.play();
} @Transactional(propagation = Propagation.REQUIRES_NEW)
private void scrobble() {
musicCatalogueService.scrobble(song);
}
}
上面这个例子里,如果musicCatalogueService.scrobble(song)调用失败了,playSong()也会失败。
因为playSong()和scrobble()在同一个事务中。
所以要开启新事务,方法必须声明为public。
译注:
这里有点问题。即使将scrobble()声明为public,scrobble()也不会开启新事务。
这是因为Spring是使用AOP来进行事务管理的。而scrobble()和playSong()在一个类里,当playSong()调用scrobble()时,是直接调用scrobble()而不是调用代理方法,所以这两个方法都在同一个事务中。而musicCatalogueService.scrobble(song)是另一个对象(musicCatalogueService)中的方法,这个对象由Spring注入,是可以通过AOP代理的,也就可以通过注解开启新事务(当然前提是,musicCatalogueService的方法有注解)。
小结:
(1)@Transactional注解对私有方法不起作用,只对公有方法生效。
(2)Spring使用AOP进行事务管理,因此同一个类中的方法互相调用,在不涉及其他类的方法时,如果第一个方法开启了事务,那么接下来所有的方法都处于同一个事务中(不论其他方法是否私有/公有、是否有注解、注解的传播级别是什么)。
(3)只有调用不同类的方法时,才有可能开启新事务。
2. 同一个类中的方法调用
如果一个方法调用另一个方法,而这个被调用方法要开启新事务的话,它必须在另一个类中。
不然,这两个方法在同一个事务中。
把方法放在不同的类中来开启新事务的例子:
@Transactional
public class MusicPlayerService { @Autowired
Song song; @Autowired
MusicCatalogueService musicCatalogueService; public void playSong() {
musicCatalogueService.scrobble(song);
song.play();
}
} public class MusicCatalogueService { @Autowired
ScrobbleRepository scrobbleRepository; @Transactional(propagation = Propagation.REQUIRES_NEW)
public void scrobble(Song song) {
scrobbleRepository.save(song);
}
}
3. SUPPORTS和readonly结合
如果没有正在进行的事务,那么SUPPORTS不会创建新事务。readonly会被忽视。
4. CRD操作和readonly结合
如果我们使用了REQUIRED或者REQUIRES_NEW,以及readonly,然后尝试做CREATE/DELETE/UPDATE操作,那么程序会抛出只读异常。
5. Checked Exceptions
如果程序抛出RuntimeException,事务会回滚。这很合理。
但是如果程序抛出的是checked exceptions呢?
答案是:事务不会回滚。
那怎样去处理这种情况?
Spring提供了rollbackFor属性。通过指定要回滚的异常类型,可以确保在程序抛出checked exceptions时事务回滚。用法如下:
@Transactional(rollbackFor = Exception.class)
public void rollBackActionDefinedMethod() {
}
译文完。
Spring Framework中常见的事务传播陷阱(译文)的更多相关文章
- Spring Framework 中启动 Redis 事务操作
背景: 项目中遇到有一系列对Redis的操作,并需要保持事务处理. 环境: Spring version 4.1.8.RELEASE Redis Server 2.6.12 (64位) spring- ...
- 事务特性,事务的隔离级别以及spring中定义的事务传播行为
.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...
- 转-Spring Framework中的AOP之around通知
Spring Framework中的AOP之around通知 http://blog.csdn.net/xiaoliang_xie/article/details/7049183 标签: spring ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中的spring web MVC模块
spring framework中的spring web MVC模块 1.概述 spring web mvc是spring框架中的一个模块 spring web mvc实现了web的MVC架构模式,可 ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中web相关的知识(概述)
Spring Framework中web相关的知识 1.概述: 参考资料:官网documentation中第22小节内容 关于spring web mvc: spring framework中拥有自 ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->关于spring framework中的beans
Spring framework中的beans 1.概述 bean其实就是各个类实例化后的对象,即objects spring framework的IOC容器所管理的基本单元就是bean spring ...
- Spring支持的常用数据库事务传播属性和隔离级别
事务的四大特征:原子性,隔离性,持久性,一致性 spring提供了7种事务传播属性: 一个事务与其他事务的隔离程度称为隔离级别.不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性 ...
- 实例详解 EJB 中的六大事务传播属性--转
前言 事务 (Transaction) 是访问并可能更新数据库中各种数据项的一个程序执行单元 (unit).在关系数据库中,一个事务可以是一条或一组 SQL 语句,甚至整个程序.它有通常被称为 ACI ...
- 在Spring Boot中使用数据库事务
我们在前面已经分别介绍了如何在Spring Boot中使用JPA(初识在Spring Boot中使用JPA)以及如何在Spring Boot中输出REST资源(在Spring Boot中输出REST资 ...
随机推荐
- java程序设计基础篇 复习笔记 第六单元
第六章 一维数组 1 数组初始化语法 array initializer 2 for each loop 3 off-by-one error 通常是在循环中该使用<的地方使用了<= 4 ...
- 十四、dbms_obfuscation_toolkit(用于加密和解密应用数据)
1.概述 作用:用于加密和解密应用数据,另外还可以生成密码检验和.通过加密输入数据,可以防止黑客或其他用户窃取私有数据;而通过结合使用加密和密码检验和,可以防止黑客破坏初加密的数据.当使用该包加密数据 ...
- nginx的编译,和简单的配置问题
反向代理常见的lvs.haproxy. 缓存服务常见的.squid.vanish.常见的前端缓存.Apache是多进程的web服务器,Nginx是多线程的web服务器. Nginx的特点,对静态能力强 ...
- ios 第2天
类的方法和实例的方法 -(void)runwithspeed:(int)speed and direction:(int)direction; 实例方法 -开头 运用对象调用 函数名为runwiths ...
- web服务器无法显示font-awesome字体图标
今天遇到了在本地运行网页 一切调用的额font的小图标都OK的,但是把网页发布到tomcat服务器上面就不行了 之后百度了下,找到了解决方法,遂记录下,方法如下: 在web.xml 文件中加上: &l ...
- Spring核心概念(一)
1.解决JavaEE的轻量级框架. 2.环境搭建 第一步:导入spring的jar包 第二步:导入配置文件(一般写在resource下面) 第三步:创建一个类(bean) 第四步:在主配置文件中注入这 ...
- (二) ffmpeg filter学习--混音实现
Audio 混音实现 从FFMPEG原生代码doc/examples/filtering_audio.c修改而来. ffmpeg版本信息 ffmpeg version N-82997-g557c0df ...
- React-Native基础_1.初识React-Native项目
1.初识React-Native项目 'use strict'//使用严格模式 import React, { Component } from 'react';//导入React的Component ...
- pdf 转图片,提取图片研究心得
1.pdf 中的数据是有多种编码的,详情请看:http://www.cnblogs.com/zendu/p/7644465.html 2.我的工作场景比较特殊,pdf中全部是图片,所以pdf转图片就有 ...
- 【剑指offer】之字形打印二叉树,C++实现
原创文章,转载请注明出处! 本题牛客网地址 博客文章索引地址 博客文章中代码的github地址 1.题目 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打 ...