spring之事务的传播行为(三)
(1)当事务被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事物,并在自己的事务中运行。
(2)事务的传播行为可以由传播属性指定,spring定义了7种传播行为,最常用的是REQUIRED和REQUIRED_NEW。
在上一节我们利用事务解决了购买时候的问题,本节继续介绍事务的传播行为。
新建Cashier.java
package com.gong.spring.tx;
import java.util.List;
public interface Cashier {
public void checkout(String username, List<String> isbns);
}
新建CashierImpl.java
package com.gong.spring.tx;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("cashier")
public class CashierImpl implements Cashier {
@Autowired
private BookShopService bookShopService;
@Transactional
@Override
public void checkout(String username, List<String> isbns) {
for(String isbn: isbns){
bookShopService.purchase(username, isbn);
}
}
}
意思是checkout是一个添加了事务的方法,而在该方法里调用了一个也添加了事务的方法bookShopService,那么在checkout中到底是用bookShopService中的事务,还是用自己本身的事务?我们以实际结果来看。
现在重新设置数据库中的数据:
我们在SpringTransactionTest中测试checkout方法:
private Cashier cashier = null;
cashier = ctx.getBean(Cashier.class);
@Test
public void testTransactionlPropagation(){
cashier.checkout("AA", Arrays.asList("1001", "1002"));
}
两本都是可以购买成功的:
此时,我们再次运行SpringTransactionTest中的testTransactionlPropagation方法:
会抛出异常:
这是因为买了第一本之后剩30,不够买第二本,我们看看数据库中的结果:
却发现一本也没有买成功,这就是事务默认的传播行为,即在现有的事务内继续运行,也就是purcase方法上的注解实际默认是@Transactional(propagation=Propagation.REQUIRED)。因此checkout和bookShopService自始至终都在一个事务中,这个事务只在checkout结束的时候被提交,因此用户一本书都买不到。
使用@Transactional(propagation=Propagation.REQUIRES_NEW)来表示方法新开一个事务,如果该方法被另一个事务方法所调用,那么调用的事务方法就暂时被挂起。也就是说,为purchase方法加上了@Transactional(propagation=Propagation.REQUIRES_NEW)之后,purchase会在自己的事务中运行,并且在运行完之后,再运行checkout的事务。
我们为purchase上加上@Transactional(propagation=Propagation.REQUIRES_NEW)注解,再看下结果:
可以成功的买到一本。
- SpringMVC入门就这么简单
- pl/sql中的forall简单测试(r5笔记第63天)
- SpringMVC【开发Controller】详解
- 巧用外部表备份历史数据(r5笔记第62天)
- Github 项目推荐 | 最小化类 AlphaGo Zero 引擎 —— Nochi
- 半自动化运维之快速连接到指定环境(一) (r5笔记第61天)
- Spring【DAO模块】知识要点
- 浅谈exp/imp(上) (r5笔记第81天)
- Java高并发秒杀系统【观后总结】
- 【专业技术】引擎算法探究
- 阅读SSM项目之scm
- 阅读SSH项目之ERP
- Hybris商品图片导入与压缩有关的配置
- 一条sql语句的建议调优分析(r5笔记第73天)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 【Centos8】安装docker的坎坷历程
- 你不知道的Virtual DOM(一):Virtual Dom介绍
- Under the Hood: NaN of JS
- 带上问题来学redis,看到不吃亏(什么是redis?缓存问题、数据一致性、redis配置文件汉化版)
- 基于weex的有赞无线开发框架
- 搭建简易的物联网服务端和客户端-第四次增补(二十六)
- 实习第十一周,第十二周
- Cordova安装
- django-ckeditor本地图片上传功能
- ESP32 windows下编译环境搭建
- Android hex十六进制转String
- “Ajax请求后台,后台两次session不一致”问题解决
- Angularjs动态加载ECharts(一)
- NodeMCU连接wifi语句报错:“stdin:1: bad argument #1 to 'config' (config table not found!)”
- Angularjs动态加载ECharts(二)