最近看到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中常见的事务传播陷阱(译文)的更多相关文章

  1. Spring Framework 中启动 Redis 事务操作

    背景: 项目中遇到有一系列对Redis的操作,并需要保持事务处理. 环境: Spring version 4.1.8.RELEASE Redis Server 2.6.12 (64位) spring- ...

  2. 事务特性,事务的隔离级别以及spring中定义的事务传播行为

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  3. 转-Spring Framework中的AOP之around通知

    Spring Framework中的AOP之around通知 http://blog.csdn.net/xiaoliang_xie/article/details/7049183 标签: spring ...

  4. 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架构模式,可 ...

  5. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中web相关的知识(概述)

    Spring Framework中web相关的知识 1.概述: 参考资料:官网documentation中第22小节内容 关于spring web mvc:  spring framework中拥有自 ...

  6. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->关于spring framework中的beans

    Spring framework中的beans 1.概述 bean其实就是各个类实例化后的对象,即objects spring framework的IOC容器所管理的基本单元就是bean spring ...

  7. Spring支持的常用数据库事务传播属性和隔离级别

    事务的四大特征:原子性,隔离性,持久性,一致性 spring提供了7种事务传播属性: 一个事务与其他事务的隔离程度称为隔离级别.不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性 ...

  8. 实例详解 EJB 中的六大事务传播属性--转

    前言 事务 (Transaction) 是访问并可能更新数据库中各种数据项的一个程序执行单元 (unit).在关系数据库中,一个事务可以是一条或一组 SQL 语句,甚至整个程序.它有通常被称为 ACI ...

  9. 在Spring Boot中使用数据库事务

    我们在前面已经分别介绍了如何在Spring Boot中使用JPA(初识在Spring Boot中使用JPA)以及如何在Spring Boot中输出REST资源(在Spring Boot中输出REST资 ...

随机推荐

  1. 拒绝了对对象 'sp_OACreate' (数据库 'mssqlsystemresource',架构 'sys')的 EXECUTE 权限。

    执行一个存储过程, 由于里面使用到了一些 --创建对象  EXEC sp_OACreate 'VBScript.RegExp', @objRegex OUT  --设置属性  EXEC sp_OASe ...

  2. linux 字符串查找

    获取指定目录文件名包含指定字符的文件,然后遍历是否有包含特定字符串,有的话打出文件名 #!/bin/sh COMMAND=`find /data/home/ftp/data/20/201704/27/ ...

  3. 简单的cookie盗取

    此文需要有一定的javascript\html\php方面的只是作为基础 直接上代码: #用于抓取盗窃来的cookie的php文件,此文件需置于攻击者的服务器上,这里包含了两种写法:Method1和M ...

  4. office在繁体系统下 导入导出 功能灰显的解决方法

    当在win7系统使用繁体中文版的office时,或系统是繁体版时,可能会导致office的导入导出功能无法使用 解决方法: 控制面板--区域和语言--格式--中文简体

  5. L151

    In Toothy Prequel, Piranha-Like Fish Menaced Jurassic Seas You can call it a prehistoric prequel.Sci ...

  6. Java中关于内存泄漏出现的原因以及如何避免内存泄漏

    转账自:http://blog.csdn.net/wtt945482445/article/details/52483944 Java 内存分配策略 Java 程序运行时的内存分配策略有三种,分别是静 ...

  7. 常见Git操作及关键知识点

    一.Git三区概念 工作区 (work dict) 暂存区(stage)(add 是添加到当前的暂存区) 提交区(就是当前工作的分支master分支或者branches分支) git 所有操作都是基于 ...

  8. 【剑指offer-21】调整数组顺序使奇数位于偶数前面,C++实现(冒泡排序)

    1.题目 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分. 2.思路 本题有两种解法,一种是不保证数组稳定性的解法,一种是保 ...

  9. 【pandas】生日转年龄

    数据挖掘比赛中,获得的数据中可能有个人的生日,在数据分析中并不需要生日,而是需要年龄.不同年龄会呈现不同的状态,比如收入.健康.居住条件等,年龄能够很好的把不同样本的差异性进行大范围的划分.下面讲述如 ...

  10. HDU1671 水题字典树

    #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #inc ...