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

1 CREATE TABLE `biz_shoe` (
2   `shoe_uuid` char(32) NOT NULL,
3   `inventory_number` int(11) DEFAULT NULL COMMENT ‘库存数量‘,
4   `is_putaway` int(1) DEFAULT NULL COMMENT ‘是否上架‘,
5   PRIMARY KEY (`shoe_uuid`)
6 ) ENGINE=InnoDB DEFAULT CHARSET=utf8

给库存赋值,如图

3.基于悲观锁实现

 1   /**
 2      * 悲观锁
 3      * @param shoe
 4      * @return
 5      */
 6     @Transactional(添加spring事务注解)
 7     @Override
 8     public Integer vieShoe(BizShoe shoe) {
 9         //抢单商品加悲观锁
10         BizShoe modleShoe = shoeMapper.lockForUpdate(shoe.getShoeUuid());
11         //商品库存
12         Integer number = modleShoe.getInventoryNumber();
13         System.out.println("库存:" + number);
14         System.out.println("线程名称:" + Thread.currentThread().getName());
15         if (number != 0) {
16             number = number - 1;
17             System.out.println("剩余库存:" + number);
18             modleShoe.setInventoryNumber(number);
19             shoeMapper.updateByPrimaryKeySelective(modleShoe);
20         } else {
21             AssertUtil.isTrue(number == 0, StatusCode.NumberIsNull, StatusCode.NumberIsNull.getMessage());
22         }
23         return number;
24     }

在mapping中具体sql语句  

1   <select id="lockForUpdate" parameterType="java.lang.String" resultMap="BaseResultMap">
2
3     SELECT <include refid="Base_Column_List" /> FROM `biz_shoe` WHERE shoe_uuid = #{shoeUuid,jdbcType=CHAR} FOR UPDATE;
4
5   </select>

4.基于乐观锁

 1   /**
 2      * 乐观锁
 3      * @param shoe
 4      * @return
 5      */
 6     @Transactional
 7     @Override
 8     public Integer vieShoe(BizShoe shoe) {
 9
10         //抢单商品加乐观锁
11         BizShoe modleShoe = shoeMapper.selectByPrimaryKey(shoe.getShoeUuid());
12         //商品库存
13         Integer number = modleShoe.getInventoryNumber();
14         System.out.println("库存:" + number);
15         System.out.println("线程名称:" + Thread.currentThread().getName());
16         if(number >0){
17             int susus = shoeMapper.updateByShoeUuidInventoryNumber(shoe.getShoeUuid(),number);
18             System.out.println("更新成功 "+susus);
19             if(susus==1){//更新成功才算抢单成功
20                 //商品库存
21                 BizShoe modleShoeNew = shoeMapper.selectByPrimaryKey(shoe.getShoeUuid());
22                 System.out.println("新库存:" + modleShoeNew.getInventoryNumber());
23             }else{
24                 AssertUtil.isTrue(true, StatusCode.NumberIsNull, StatusCode.NumberIsNull.getMessage());
25             }
26         }else {
27             AssertUtil.isTrue(true, StatusCode.NumberIsNull, StatusCode.NumberIsNull.getMessage());
28         }
29         return number;
30     }

sql语句

1 <update id="updateByShoeUuidInventoryNumber" parameterType="com.zstax.springtest.bean.BizShoe">
2
3     UPDATE biz_shoe SET inventory_number=inventory_number-1 WHERE
4     shoe_uuid=#{shoeUuid,jdbcType=CHAR} and inventory_number=#{InventoryNumber,jdbcType=INTEGER}
5
6   </update>

原文地址:https://www.cnblogs.com/sqy123/p/10354498.html

时间: 2024-08-29 03:12:20

spring事务详解(二)实例的相关文章

Spring事务详解

Spring事务机制主要包括声明式事务和编程式事务,此处侧重讲解声明式事务,编程式事务在实际开发中得不到广泛使用,仅供学习参考. Spring声明式事务让我们从复杂的事务处理中得到解脱.使得我们再也无需要去处理获得连接.关闭连接.事务提交和回滚等这些操作.再也无需要我们在与事务相关的方法中处理大量的try-catch-finally代码.我们在使用Spring声明式事务时,有一个非常重要的概念就是事务属性.事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成.我们在进行事

Spring事务详解(转)

Spring事务机制主要包括声明式事务和编程式事务,此处侧重讲解声明式事务,编程式事务在实际开发中得不到广泛使用,仅供学习参考. Spring声明式事务让我们从复杂的事务处理中得到解脱.使得我们再也无需要去处理获得连接.关闭连接.事务提交和回滚等这些操作.再也无需要我们在与事务相关的方法中处理大量的try…catch…finally代码.我们在使用Spring声明式事务时,有一个非常重要的概念就是事务属性.事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成.我们在进行事

spring事务详解(一)初探讨

一.什么是事务 维基百科:数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成.理解:事务(Transaction)是数据库区别于文件系统的重要特性之一.传统关系型数据库设计原则是满足 ACID特性,用以保证数据库事务的正确执行.Mysql的innoDB引擎就很好的支持了ACID. 二.事务的ACID特性 (箭头后,翻译自官网介绍:InnoDB and the ACID Model ) 1,原子性(Atomicity):一个事务必须被视为一个不可分割的

spring 事务详解

基于注解方式 事务,一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 事务应该具有4个属性:原子性.一致性.隔离性.持久性. 原子性(atomicity).一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做. 一致性(consistency).事务必须是使数据库从一个一致性状态变到另一个一致性状态.一致性与原子性是密切相关的. 隔离性(isolation).一个事务的执行不能被其他事务干扰.即一个事务内部的操作及

Rxjava2 Observable的辅助操作详解及实例(二)

目录 8. TimeInterval 9. Timeout 9.1 timeout(timeout, timeUnit) 9.2 timeout(timeout, timeUnit, scheduler, other) 9.3 timeout(Function itemTimeoutIndicator, ObservableSource other) 10. Timestamp 11. Using 12. To 小结 接续上篇: Rxjava2 Observable的辅助操作详解及实例(一) 8

Rxjava2 Observable的数据变换详解及实例(二)

目录 1. Window 1.1 window(closingSelector) 1.2 window(openingIndicator, closingIndicator) 1.3 window(count) 1.4 window(count, skip) 1.5 window(timespan, TimeUnit) 1.6 window(timespan, TimeUnit, count) 1.7 window(timespan, timeskip, TimeUnit) 2. GroupBy

Rxjava2 Observable的数据过滤详解及实例(二)

目录 6. Filter 7. Frist 7.1 firstElement() 7.2 first(defaultItem) 7.3 firstOrError() 8. Single 8.1 singleElement() 8.2 single(defaultItem) 8.3 singleOrError() 9. ElementAt 9.1 elementAt(index) 9.2 elementAt(index, defaultItem) 9.3 elementAtOrError(inde

Spring JDBC详解

<Spring JDBC详解> 本文旨在讲述Spring JDBC模块的用法.Spring JDBC模块是Spring框架的基础模块之一. 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.概述 在Spring JDBC模块中,所有的类可以被分到四个单独的包:1)core即核心包,它包含了JDBC的核心功能.此包内有很多重要的类,包括:JdbcTemplate类.SimpleJdbcInsert类,SimpleJdbcCall类,以及NamedP

J2EE进阶(四)Spring配置文件详解

J2EE进阶(四)Spring配置文件详解 前言 Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的"图纸".Java EE程序员必须学会并灵活应用这份"图纸"准确地表达自己的"生产意图".Spring配置文件是一个或多个标准的XML文档,applicationContext.xml是Spring的默认配置文件,当容器启动时找不到指定的配置文档时,将会尝试加载这个默认的配置文件. 下面列举的是