前述

​ 这段时间在工作中碰到一个事务相关的问题。先说下这个问题的场景,我们是一个商城项目,正在开发优惠券模块,现在有一个需求是需要批量领取优惠券,而且在领券时,其中一张领取失败不能影响其他符合要求的券的领取。由于之前在开发时,在领券这一块一直做的是单张领取,所以在做批量的时候很简单的做了个循环,然后封装成一个批量领券的方法中。伪代码如下:

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class CouponService {
/**
* 单独领取某张券
* @param couponCode
* @return
*/
public Coupon get(String couponCode) {
log.info("查询是否存在这个券");
if ("001".equals(couponCode) || "002".equals(couponCode)) {
return Coupon.builder().code(couponCode).name("优惠券A").build();
}
// 自定义的异常类,专门指定不符合规则的券被领取时抛出的状态
throw new CustomeException("不存在这个优惠券");
} /**
* 批量领取
* @param codes
* @return
*/
public List<Coupon> batchGet(List<String> codes) {
List<Coupon> target = new ArrayList<>();
codes.forEach(code -> {
Coupon coupon = null;
try {
coupon = get(code);
} catch (CustomeException e) {
log.error(e.getMessage());
}
target.add(coupon);
});
return target;
}
}

上面的方法在执行时会抛出异常

Transaction rolled back because it has been marked as rollback-only

我们来分析下这个异常:

首先我们要知道,spring中事务的默认传播机制是

PROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启

​ 在这种传播机制下,batchGet方法跟循环中的get方法会共享一个事务,而在get方法抛出异常时,这个事务已经被标记为rollback-only了,在这种情况下,batchGet方法捕获了这个异常并没有继续向上抛出,所以会执行commit操作,而对一个被标记成rollback-only的方法执行commit操作,就会抛出以上错误。

​ 我的解决办法就是,在batcGet方法上将事务的隔离级别设置为PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行

好了,这个异常我们分析完了,现在我们进入我们这篇文章需要学的主题内容,主要是事务的传播机制及隔离级别。预期两篇文章,一篇理想学习,一篇源码分析,源码分析将以SpringBoot为主。希望能跟大家一起进步,学习,每天进步一点点就好~~~

Spring中事务的传播机制:

  1. ROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启

解释:当A.methodA()和B.methodB()都打上REQUIRED的事务标志,执行A.methodA()方法的时候,看到上下文没有事务,会新建一个事务,当执行到b.methodB()的时候,发现上下文已经有事务了,则不会新建事务,用A.methodA()新建的那个事务。如果b.methodB()执行成功,a.methodA()执行失败,那么b.methodB()和a.methodA()都会回滚(用的都是a.methodA()的事务)

  1. PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行

解释:当B.methodB()打上PROPAGATION_SUPPORTS的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则b.methodB()沿用该事务,反之b.methodB()就以非事物的方式执行

3. PROPAGATION_MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常

解释:当B.methodB()打上PROPAGATION_MANDATORY的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则b.methodB()沿用该事务,如果没有,则会抛出异常

4.PROPAGATION_REQUIRES_NEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起

解释:当B.methodB()打上PROPAGATION_REQUIRES_NEW的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则会挂起A.methodA()的事务,新建一个属于b.methodB(),当b.methodB()的事务执行结束的时候,则会唤醒b.methodB()的事务。和PROPAGATION_REQUIRED的差别在于回滚,当b.methodB()的事务提交后,A.methodA()执行失败,只会回滚A.methodA不会回滚b.methodB(),当b.methodB()执行失败,异常被A.methodA()方法catch到的话,A.methodA()事务不会回滚

  1. PROPAGATION_NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务

解释:当B.methodB()打上PROPAGATION_NOT_SUPPORTED的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则会挂起A.methodA()的事务,当执行完b.methodB()方法的时候,A.methodA()方法继续以事务的方式执行

  1. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常

解释:当B.methodB()打上PROPAGATION_NEVER的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果有事务,则抛出异常,如果没有则以非事务执行

  1. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, PROPAGATION_REQUIRED 属性执行

解释:当B.methodB()打上PROPAGATION_NOT_SUPPORTED的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,如果A.methodA()方法有事务,则会用当前事务,如果 b.methodB()执行失败,只会回滚 b.methodB(),不会回滚A.methodA(),只有当A.methodA()执行完成后才会提交b.methodB()的事务,如果A.methodA()方法没有事务,就会新建一个事务;

Spring中事物的隔离级别

事务隔离级别:

ISOLATION_DEFAULT,

ISOLATION_READ_UNCOMMITTED,

ISOLATION_READ_COMMITTED,

ISOLATION_REPEATABLE_READ,

ISOLATION_GENERALIZABLE

1.ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别

2. ISOLATION_READ_UNCOMMITTED :这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

3. ISOLATION_READ_COMMITTED :保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。:

4. ISOLATION_REPEATABLE_READ :这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。

5. ISOLATION_SERIALIZABLE :这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。

spring学习笔记(九)事务学习(上)的更多相关文章

  1. 学习笔记:CentOS7学习之十九:Linux网络管理技术

    目录 学习笔记:CentOS7学习之十九:Linux网络管理技术 本文用于记录学习体会.心得,兼做笔记使用,方便以后复习总结.内容基本完全参考学神教育教材,图片大多取材自学神教育资料,在此非常感谢MK ...

  2. 软件测试之loadrunner学习笔记-01事务

    loadrunner学习笔记-01事务<转载至网络> 事务又称为Transaction,事务是一个点为了衡量某个action的性能,需要在开始和结束位置插入一个范围,定义这样一个事务. 作 ...

  3. WCF学习笔记之事务编程

    WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...

  4. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  5. MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九

    <Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次   SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...

  6. go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin)

    目录 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin) zipkin使用demo 数据持久化 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin ...

  7. c++学习笔记之封装篇(上)

    title: c++学习笔记之封装篇(上) date: 2017-03-12 18:59:01 tags: [c++,c,封装,类] categories: [学习,程序员,c/c++] --- 一. ...

  8. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者http://www.admin10000.com/document/96 ...

  9. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

  10. Spark学习笔记2——RDD(上)

    目录 Spark学习笔记2--RDD(上) RDD是什么? 例子 创建 RDD 并行化方式 读取外部数据集方式 RDD 操作 转化操作 行动操作 惰性求值 Spark学习笔记2--RDD(上) 笔记摘 ...

随机推荐

  1. Web三维编程入门总结之三:3D碰撞检测初探

    自己动手写一个方法比分析他人的写的方法困难很多,由此而来的对程序的进一步理解也是分析别人的代码很难得到的. 一.先来几张效果图: 1.场景中有两个半径为1的球体,蓝色线段从球心出发指向球体的“正向” ...

  2. Python-selenium-自动化测试模型

    1.线性测试 优势:每一个脚本都是完整独立的,每一个脚本对应一个测试用例 缺点:开发成本高,会有重复操作重复脚本:维护成本也高,修改重复操作的脚本时,要逐一进行修改. 2.模块化驱动测试 把重复的操作 ...

  3. 统计子串数量,Python基础

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:陈YL PS:如有需要Python学习资料的小伙伴可以加点击下方链接自 ...

  4. pandas basic cheatsheet

    "胖的要死"是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具. 有多大?这篇 ...

  5. H - Tempter of the Bone DFS

    小明做了一个很久很久的梦,醒来后他竟发现自己和朋友在一个摇摇欲坠的大棋盘上,他们必须得想尽一切办法逃离这里.经过长时间的打探,小明发现,自己所在的棋盘格子上有个机关,上面写着“你只有一次机会,出发后t ...

  6. Numpy学习-(2)

    我学习numpy过程的记录 1. 切片和索引 (1) 两种切片方式示例: (2) 多维数组: import numpy as np a = np.array([[1,2,3],[3,4,5],[4,5 ...

  7. Upload-Labs 实验操作记录

    0x01 安装 下载:https://github.com/c0ny1/upload-labs 环境:简单搭建phpstudy环境即可,记得在upload-labs根目录下创建该文件夹 0x02 文件 ...

  8. eclipse集成 json editor plugin插件

    打开eclipse 找到: help--->install new software ——>add name:jsoneditor location:https://marketplace ...

  9. 【启蒙】C笔记之初学阶段(下篇)

    下篇继续点赞,谢谢老铁,不存在下次一定的哈! c语言简单判断质数的方法 int isprime(int a){ ) ; ==||a==||a==) ; else { ;i<=sqrt(a);i+ ...

  10. BUAA_OO 第一单元总结

    1.简单多项式求导 第一次作业的难点,我认为是对输入的预处理,尤其是正则表达式的使用.这次作业的思路是:首先将表达式进行预处理,(由于题目中要求不会有空格产生的WF,所以可以放心大胆的消除空格). 消 ...