spring事务详解(二)实例
在Spring中,事务有两种实现方式:
编程式事务管理: 编程式事务管理使用底层源码可实现更细粒度的事务控制。spring推荐使用TransactionTemplate,典型的模板模式。
申明式事务管理: 添加@Transactional注解,并定义传播机制+回滚策略。基于Spring AOP实现,本质是对方法前后进行拦截,
方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
关于spring事务实现方式:
引用博文:https://www.cnblogs.com/dennyzhangdd/p/9708499.html
关于分布式锁的实现方式:
引用博文:https://www.cnblogs.com/dennyzhangdd/p/7133653.html
提供一个具体实例来说明如何使用spring事务
基于数据库锁实现
1.悲观锁:select for update(一致性锁定读)

查询官方文档如上图,事务内起作用的行锁。能够保证当前session事务所锁定的行不会被其他session所修改(这里的修改指更新或者删除)。
对读取的记录加X锁,即排它锁,其他事不能对上锁的行加任何锁。 BEGIN;(确保以下2步骤在一个事务中:)
SELECT * FROM tb_product_stock WHERE product_id=1 FOR UPDATE--->product_id有索引,锁行.加锁
(注:条件字段必须有索引才能锁行,否则锁表,且最好用explain查看一下是否使用了索引,因为有一些会被优化掉最终没有使用索引)
UPDATE tb_product_stock SET number=number-1 WHERE product_id=1--->更新库存-1.解锁
COMMIT;
2.乐观锁:版本控制
选一个字段作为版本控制字段,更新前查询一次,更新时该字段作为更新条件。
不同业务场景,版本控制字段,可以0 1控制,也可以+1控制,也可以-1控制,这个随意。
BEGIN;(确保以下2步骤在一个事务中:)
SELECT number FROM tb_product_stock WHERE product_id=1--》查询库存总数,不加锁
UPDATE tb_product_stock SET number=number-1 WHERE product_id=1 AND number=第一步查询到的库存数--》number字段作为版本控制字段
COMMIT;
场景举例:
卖商品,先查询库存>0,更新库存-1。
例如:一种商品,有两件库存,多人来下单买,一个人一次只能买一件商品
创建表biz_shoe
CREATE TABLE `biz_shoe` (
`shoe_uuid` char(32) NOT NULL,
`inventory_number` int(11) DEFAULT NULL COMMENT '库存数量',
`is_putaway` int(1) DEFAULT NULL COMMENT '是否上架',
PRIMARY KEY (`shoe_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
给库存赋值,如图

3.基于悲观锁实现
/**
* 悲观锁
* @param shoe
* @return
*/
@Transactional(添加spring事务注解)
@Override
public Integer vieShoe(BizShoe shoe) {
//抢单商品加悲观锁
BizShoe modleShoe = shoeMapper.lockForUpdate(shoe.getShoeUuid());
//商品库存
Integer number = modleShoe.getInventoryNumber();
System.out.println("库存:" + number);
System.out.println("线程名称:" + Thread.currentThread().getName());
if (number != 0) {
number = number - 1;
System.out.println("剩余库存:" + number);
modleShoe.setInventoryNumber(number);
shoeMapper.updateByPrimaryKeySelective(modleShoe);
} else {
AssertUtil.isTrue(number == 0, StatusCode.NumberIsNull, StatusCode.NumberIsNull.getMessage());
}
return number;
}
在mapping中具体sql语句
<select id="lockForUpdate" parameterType="java.lang.String" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" /> FROM `biz_shoe` WHERE shoe_uuid = #{shoeUuid,jdbcType=CHAR} FOR UPDATE;
</select>
4.基于乐观锁
/**
* 乐观锁
* @param shoe
* @return
*/
@Transactional
@Override
public Integer vieShoe(BizShoe shoe) { //抢单商品加乐观锁
BizShoe modleShoe = shoeMapper.selectByPrimaryKey(shoe.getShoeUuid());
//商品库存
Integer number = modleShoe.getInventoryNumber();
System.out.println("库存:" + number);
System.out.println("线程名称:" + Thread.currentThread().getName());
if(number >0){
int susus = shoeMapper.updateByShoeUuidInventoryNumber(shoe.getShoeUuid(),number);
System.out.println("更新成功 "+susus);
if(susus==1){//更新成功才算抢单成功
//商品库存
BizShoe modleShoeNew = shoeMapper.selectByPrimaryKey(shoe.getShoeUuid());
System.out.println("新库存:" + modleShoeNew.getInventoryNumber());
}else{
AssertUtil.isTrue(true, StatusCode.NumberIsNull, StatusCode.NumberIsNull.getMessage());
}
}else {
AssertUtil.isTrue(true, StatusCode.NumberIsNull, StatusCode.NumberIsNull.getMessage());
}
return number;
}
sql语句
<update id="updateByShoeUuidInventoryNumber" parameterType="com.zstax.springtest.bean.BizShoe">
UPDATE biz_shoe SET inventory_number=inventory_number-1 WHERE
shoe_uuid=#{shoeUuid,jdbcType=CHAR} and inventory_number=#{InventoryNumber,jdbcType=INTEGER}
</update>
spring事务详解(二)实例的更多相关文章
- spring事务详解(二)简单样例
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- spring事务详解(三)源码详解
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- spring事务详解(一)初探事务
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 引子 很多 ...
- spring事务详解(五)总结提高
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.概念 ...
- spring事务详解(四)测试验证
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- Spring Aop 详解二
这是Spring Aop的第二篇,案例代码很详解,可以查看https://gitee.com/haimama/java-study/tree/master/spring-aop-demo. 阅读前,建 ...
- spring事务详解(转载+高亮)
spring提供的事务管理可以分为两类:编程式的和声明式的.编程式的,比较灵活,但是代码量大,存在重复的代码比较多:声明式的比编程式的更灵活.编程式主要使用transactionTemplate.省略 ...
- Spring、Spring事务详解;使用XML配置事务
@Transactional可以设置以下参数: @Transactional(readOnly=false) // 指定事务是否只读的 true/false @Transactional(rollba ...
- JAVA框架之Spring【Spring事务详解】
spring提供的事务管理可以分为两类:编程式的和声明式的.编程式的,比较灵活,但是代码量大,存在重复的代码比较多:声明式的比编程式的更灵活.编程式主要使用transactionTemplate.省略 ...
随机推荐
- 【Alpha】第一次Scrum Meeting
本次会议内容概括如下: 总结了一周以来大家任务的完成情况,对消耗时间进行统计,并评估了各自对团队的贡献(影响)程度 整理并融合所有人的工作的结果生成了相应的总结性文档 进一步明确了团队中各个成员的定位 ...
- 如何运行spring项目,并打成jar包进行发布
一.创建spring项目 1.创建项目 2.创建moudule,选择java类型即可. 3.创建lib文件,引入spring的4个核心包spring-beans.spring-context.spri ...
- SQLSERVER 查看操作系统内存
1. 通过系统试图查看内存信息 SELECT total_physical_memory_kb / AS [物理内存(MB)] , available_physical_memory_kb / AS ...
- Python的文件读写
目录 读文件 操作文件 读取内容 面试题的例子 写文件 操作模式 指针操作 字符编码 读文件 操作文件 打开一个文件用open()方法(open()返回一个文件对象,它是可迭代的): 文件使用完毕后必 ...
- 实战基于Spring Boot 2的WebFlux和mLab搭建反应式Web
Spring Framework 5带来了新的Reactive Stack非阻塞式Web框架:Spring WebFlux.作为与Spring MVC并行使用的Web框架,Spring WebFlux ...
- MT【77】函数的定义理解
答案:D.比如C 中令$x^2+1=2,x=-1,1,$ 得$f(2)=0,2$与定义矛盾,A,B同理排除. D中注意到$x^2-2x$与$|x-1|$对称轴都是$x=1$. 评:函数的定义,首先是两 ...
- 【题解】 [HNOI2005]狡猾的商人(差分约束)
题面懒得复制,戳我戳我 Solution: 其实这个差分是挺显然的,我们可以用\(s[i]\)表示从第\(1\)到\(i\)中间的收入和 重点就在式子,比如读入\(a\),\(b\),\(c\),显然 ...
- 【Revit API】创建共享参数
话不多说,直接上代码 var app = doc.Application; app.SharedParametersFilename = sharedParamFilePath; Definition ...
- 【BZOJ1032】[JSOI2007]祖玛(动态规划)
[BZOJ1032][JSOI2007]祖玛(动态规划) 题面 BZOJ 洛谷 题解 听说是道假题,假的原因是因为出题人可能没有考虑到祖玛的骚套路,比如可以先打几个球进去再一波消掉.也就是出题人基本默 ...
- AtCoder Grand Contest 010
AtCoder Grand Contest 010 A - Addition 翻译 黑板上写了\(n\)个正整数,每次会擦去两个奇偶性相同的数,然后把他们的和写会到黑板上,问最终能否只剩下一个数. 题 ...