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是否成立,还需要再多多考虑你的业务需求。

Transaction不是一个新东西了,那对于transaction的使用会不会有一些模式?一些经验之谈呢?答案肯定是有的,以后博客再说。

Spring Transaction属性之Propagation的更多相关文章

  1. spring Transaction Propagation 事务传播

    spring Transaction中有一个很重要的属性:Propagation.主要用来配置当前需要执行的方法,与当前是否有transaction之间的关系. 我晓得有点儿抽象,这也是为什么我想要写 ...

  2. spring Existing transaction found for transaction marked with propagation 'never' 解决

    先在申明事务中配置了所有的事务 <!--配置事物传播策略,以及隔离级别--> <tx:advice id="txAdvice" transaction-manag ...

  3. spring transaction 初识

    spring 事务初识 1.spring事务的主要接口,首先盗图一张,展示出spring 事务的相关接口.Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibern ...

  4. Spring 事务 属性 详细

    学习东西要知行合一,如果只是知道理论而没实践过,那么掌握的也不会特别扎实,估计过几天就会忘记,接下来我们一起实践来学习Spring事务的传播属性. 传播属性 传播属性定义的是当一个事务方法碰到另一个事 ...

  5. Spring Transaction 使用入门

    一.开篇陈述 1.1 写文缘由 最近在系统学习spring框架IoC.AOP.Transaction相关的知识点,准备写三篇随笔记录学习过程中的感悟.这是第一篇,记录spring Transactio ...

  6. Spring学习记录1--@Transactional Propagation

    起因 学习Spring的时候就知道aop有一个应用是声明式注解..反正往Service上一丢@Transactional就完事了..不用自己去开启hibernate的session,很简单. 但是@T ...

  7. spring Transaction Management --官方

    原文链接:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html 12.  ...

  8. Spring Boot属性文件配置文档(全部)

    This sample file is meant as a guide only. Do not copy/paste the entire content into your applicatio ...

  9. springboot成神之——spring boot,spring jdbc和spring transaction的使用

    本文介绍spring boot,spring jdbc和spring transaction的使用 项目结构 依赖 application model层 mapper层 dao层 exception层 ...

随机推荐

  1. sqlite函数大全

      abs(X) 返回参数X的绝对值. coalesce(X,Y,...) 返回第一个非空参数的副本.若所有的参数均为NULL,返回NULL.至少2个参数. glob(X,Y) 用于实现SQLite的 ...

  2. 刘汝佳 算法竞赛-入门经典 第二部分 算法篇 第六章 1(Lists)

    127 - "Accordian" Patience 题目大意:一个人一张张发牌,如果这张牌与这张牌前面的一张或者前面的第三张(后面称之为一位置和三位置)的点数或花式相同,则将这张 ...

  3. ExtJs布局之viewport

    <!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...

  4. 知问前端——创建header区

    创建界面 我们首先要设计一个header,这个区域将要设计成永远置顶.也就是,往下拉出滚动条也永远在页面最上层可视区内.在header区,目前先设计LOGO.搜索框.按钮.注册和登录即可. 项目的大致 ...

  5. Learn CSS

    韩顺平老师的CSS讲的还是很简单的,仅作入门. div+css的介绍    div+css是什么. div元素是用来为HTML文档内大块(block-level)的内容提供结构和背景的元素. css是 ...

  6. BeanUtils.copyProperties与PropertyUtils.copyProperties用法及区别

    一.简介: BeanUtils提供对Java反射和自省API的包装.其主要目的是利用反射机制对JavaBean的属性进行处理.我们知道,一个JavaBean 通常包含了大量的属性,很多情况下,对Jav ...

  7. awk除去重复行

    awk去除重复行,思路是以每一行的$0为key,创建一个hash数组,后续碰到的行,如果数组里已经有了,就不再print了,否则将其print 测试文件: 用awk: 用sort+uniq好像出错了: ...

  8. android-exploitme(四):参数篡改

    今天我们来测试请求中参数的篡改,这个在web安全测试中是常用的,拦截请求包,修改参数,提交 1.  首先我们需要启动模拟器,并使用本机的代理(加上参数-partition-size的目的是为了可以往a ...

  9. Spring笔记——Spring+JDBC组合开发

      使用Spring+JDBC集成步骤如下:   1. 配置数据源 2. 配置事务.配置事务时,需要在xml配置文件中引入用于声明事务的tx命名空间,事务的配置方式有两种:注解方式和基于XML配置方式 ...

  10. Heap和Heapify

    最近复习数据结构,又回去再看塞神的课件,看到PriorityQueue的实现.自己也根据塞神的代码写一写. 下面使用Binary Heap实现了一个简单的 Max-oriented PriorityQ ...