Spring Transaction属性之Propagation
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的更多相关文章
- spring Transaction Propagation 事务传播
spring Transaction中有一个很重要的属性:Propagation.主要用来配置当前需要执行的方法,与当前是否有transaction之间的关系. 我晓得有点儿抽象,这也是为什么我想要写 ...
- spring Existing transaction found for transaction marked with propagation 'never' 解决
先在申明事务中配置了所有的事务 <!--配置事物传播策略,以及隔离级别--> <tx:advice id="txAdvice" transaction-manag ...
- spring transaction 初识
spring 事务初识 1.spring事务的主要接口,首先盗图一张,展示出spring 事务的相关接口.Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibern ...
- Spring 事务 属性 详细
学习东西要知行合一,如果只是知道理论而没实践过,那么掌握的也不会特别扎实,估计过几天就会忘记,接下来我们一起实践来学习Spring事务的传播属性. 传播属性 传播属性定义的是当一个事务方法碰到另一个事 ...
- Spring Transaction 使用入门
一.开篇陈述 1.1 写文缘由 最近在系统学习spring框架IoC.AOP.Transaction相关的知识点,准备写三篇随笔记录学习过程中的感悟.这是第一篇,记录spring Transactio ...
- Spring学习记录1--@Transactional Propagation
起因 学习Spring的时候就知道aop有一个应用是声明式注解..反正往Service上一丢@Transactional就完事了..不用自己去开启hibernate的session,很简单. 但是@T ...
- spring Transaction Management --官方
原文链接:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html 12. ...
- Spring Boot属性文件配置文档(全部)
This sample file is meant as a guide only. Do not copy/paste the entire content into your applicatio ...
- springboot成神之——spring boot,spring jdbc和spring transaction的使用
本文介绍spring boot,spring jdbc和spring transaction的使用 项目结构 依赖 application model层 mapper层 dao层 exception层 ...
随机推荐
- Pytho中两种方式导入模块的差别
1.使用import module,只是把模块导入,访问模块中的函数名或者是属性是必须使用点运算符(.)来访问,否则直接访问会提示找不到这些函数或者属性. 2.使用from numpy import ...
- Python - 装饰器使用过程中的误区
曾灵敏 - APRIL 27, 2015 装饰器基本概念 大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, C ...
- poj 1986
Distance Queries Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 8638 Accepted: 3032 ...
- GCD初步认识
//(1)用异步函数往并发队列中添加任务, //总结:同时开启三个子线程 - (void)test1 { //1.获得全局的并发队列 dispatch_queue_t queue = dispatch ...
- 思考 ”前端开发人员都在关注的 GitHub 资源“
点这里 原文: 资源 免费的计算机编程类中文书籍 免费编程书籍 计算机科学论文 codeparkshare Python初学者书籍.视频.资料.社区推荐 Python资料汇总 app应用推荐 码农周刊 ...
- ExtJs布局之BOX
<!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...
- Linux Mint 17 + 小米WIFI创建手机热点
转载:http://www.pppei.net/blog/post/690 亲测可行! 我的系统是linux mint 17.1 64位,所用wifi位小米WIFI. 以下是原文: 此方法在linux ...
- 多重背包问题II
多重背包问题II 总体积是m,每个小物品的体积是A[i] ,每个小物品的数量是B[i],每个小物品的价值是C[i] 求能够放入背包内的最大物品能够获得的最大价值 和上一个很类似 上一题体积就是价值,这 ...
- 控制台console输出信息原理理解
Eclipse控制台输出信息的控制 标签: Eclipse控制台输出信息 2015-01-02 14:11 22454人阅读 评论(1) 收藏 举报 分类: Some Tips(15) 版权声明: ...
- iOS 网络处理注意点
原文链接:http://www.jianshu.com/p/a086c33566be 一. AFN 使用注意点 1. block循环引用 bug 解决 2.请求管理者 1.请求管理者存储到内存 请求管 ...