spring Transaction中有一个很重要的属性:Propagation。主要用来配置当前需要执行的方法,与当前是否有transaction之间的关系。

我晓得有点儿抽象,这也是为什么我想要写这篇博客的原因。看了后面的例子,大家应该就明白了。

一、Propagation取值:

REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction;

SUPPORTS:如当前有transaction,则在transaction状态下执行;如果当前没有transaction,在无transaction状态下执行;

MANDATORY:必须在有transaction状态下执行,如果当前没有transaction,则抛出异常IllegalTransactionStateException;

REQUIRES_NEW:创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起;

NOT_SUPPORTED:在无transaction状态下执行;如果当前已有transaction,则将当前transaction挂起;

NEVER:在无transaction状态下执行;如果当前已有transaction,则抛出异常IllegalTransactionStateException。

二、REQUIRED与REQUIRED_NEW

上面描述的6种propagation属性配置中,最难以理解,并且容易在transaction设计时出现问题的是REQUIRED和REQURED_NEW这两者的区别。当程序在某些情况下抛出异常时,如果对于这两者不够了解,就可能很难发现而且解决问题。

下面我们给出三个场景进行分析:

场景一:

ServiceA.Java:

public class ServiceA {
@Transactional
public void callB() {
serviceB.doSomething();
}
}

ServiceB.java

public class ServiceB {
@Transactional
public void doSomething() {
throw new RuntimeException("B throw exception");
}
}
这种情况下,我们只需要在调用ServiceA.callB时捕获ServiceB中抛出的运行时异常,则transaction就会正常的rollback。

场景二

在保持场景一中ServiceB不变,在ServiceA中调用ServiceB的doSomething时去捕获这个异常,如下:

public class ServiceA {
@Transactional
public void callB() {
try {
serviceB.doSomething();
} catch (RuntimeException e) {
System.err.println(e.getMessage());
}
}
}
这个时候,我们再调用ServiceA的callB。程序会抛出org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only这样一个异常信息。原因是什么呢?

因为在ServiceA和ServiceB中的@Transactional propagation都采用的默认值:REQUREID。根据我们前面讲过的REQUIRED特性,当ServiceA调用ServiceB的时候,他们是处于同一个transaction中。如下图所示:

当ServiceB中抛出了一个异常以后,ServiceB会把当前的transaction标记为需要rollback。但是ServiceA中捕获了这个异常,并进行了处理,认为当前transaction应该正常commit。此时就出现了前后不一致,也就是因为这样,抛出了前面的UnexpectedRollbackException。

场景三

在保持场景二中ServiceA不变,修改ServiceB中方法的propagation配置为REQUIRES_NEW,如下:

public class ServiceB {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomething() {
throw new RuntimeException("B throw exception");
}
}
此时,程序可以正常的退出了,也没有抛出UnexpectedRollbackException。原因是因为当ServiceA调用ServiceB时,serviceB的doSomething是在一个新的transaction中执行的。如下图所示:

所以,当doSomething抛出异常以后,仅仅是把新创建的transaction rollback了,而不会影响到ServiceA的transaction。ServiceA就可以正常的进行commit。

当然这里把ServiceA和ServiceB放在两个独立的transaction是否成立,还需要再多多考虑你的业务需求。

spring Transaction Propagation 事务传播的更多相关文章

  1. -手写Spring注解版本&事务传播行为

    视频参考C:\Users\Administrator\Desktop\蚂蚁3期\[www.zxit8.com] 0018-(每特教育&每特学院&蚂蚁课堂)-3期-源码分析-手写Spri ...

  2. Spring 7种事务传播行为

    1.PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置. 2.PROPAGATION_SUPPORTS:支持当前事务,如 ...

  3. 面试官:说说Spring中的事务传播行为

    前言 在开发中,相信大家都使用过Spring的事务管理功能.那么,你是否有了解过,Spring的事务传播行为呢? Spring中,有7种类型的事务传播行为.事务传播行为是Spring框架提供的一种事务 ...

  4. spring常用的事务传播属性说明

    事务Transaction,就是一组操作数据库的动作集合.事务是现代数据库理论中的核心概念之一.如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务.当所有的步骤像一个操作一样被 ...

  5. spring中的事务传播机制

    1.事务的实现思想 在spring中要想某个方法具有事务,只要在方法前加一个@Transactional注解.然后spring就会利用aop思想,在这个方法执行前开启事务, 在方法执行后选择提交事务或 ...

  6. Spring中的事务传播行为

    Spring在TransactionDefinition接口中定义了7种类型的事务传播行为,它们规定了事务方法是怎样传播的. PROPAGATION_REQUIRED(最经常使用!):支持当前事务,假 ...

  7. Spring 7种事务传播类型

    转载:https://www.cnblogs.com/originate918/p/6226342.html PROPAGATION_REQUIRED及其他6种事务传播行为种类. Spring在Tra ...

  8. Spring中的事务传播行为与隔离级别

    事务传播行为 事务传播行为(为了解决业务层方法之间互相调用的事务问题): 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己 ...

  9. 【原创】spring中的事务传播特性

    关于spring的传播特性,我对其进行了详细的叙述了下: PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. 比如方法A调用方法B,如果方法 ...

随机推荐

  1. 新版Chrome自动禁用第三方插件的解决办法[转]

    原文地址:http://www.douban.com/note/375734834/?type=like Chrome的新策略里面禁用了除chrome web store下载的所有第三方扩展,这个很烦 ...

  2. python语法------时间函数

    1.导入函数库: import time 获取格式化的时间 你可以根据需求选取各种格式,但是最简单的获取可读的时间模式的函数是asctime(): #!/usr/bin/python # -*- co ...

  3. Hilbert space

    Definition A Hilbert space H is a real or complex inner product space that is also a complete metric ...

  4. bzoj 3171: [Tjoi2013]循环格

    #include<cstdio> #include<iostream> #include<cstring> #define M 10000 #define inf ...

  5. POJ 2446 最小点覆盖

    Chessboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14787   Accepted: 4607 Descr ...

  6. Rhel6-DM多路经存储配置文档

    系统环境: rhel6 x86_64 iptables and selinux disabled 主机: 主机 网卡 软件 server21.example.com eth0:192.168.122. ...

  7. struts2 标签 和 c标签的页面数据显示

    用struts2 标签显示的页面代码 <s:if test="#request.employees == null || #request.employees.size() == 0& ...

  8. iOS 自定义emoji表情键盘

    之前走了很多弯路,包括自己定以emoji表情,自己创建view类去处理图文混排 ,当把这些焦头烂额的东西处理完了才发现 ,其实系统自带键盘是如此的方便,iOS 系统自带的表情在view,textfie ...

  9. windows核心编程---第七章 用户模式下的线程同步

    用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ...

  10. H5版俄罗斯方块(5)---需求演进和产品迭代

    前言: 产品的形态是不断迭代的, 从粗糙到精致, 从简易到立体. 有了最初的技术积累和时间思考后, 终于明确了该游戏的方向. 我想说的是: 技术不是重点, 产品/用户体验才是核心议题. 结合朋友的游戏 ...