首页 > 其他分享 >六、MybatisPlus实现乐观锁

六、MybatisPlus实现乐观锁

时间:2023-03-01 11:23:38浏览次数:42  
标签:MybatisPlus 实现 productLi 乐观 商品价格 version productWang productMapper getPrice

乐观锁

场景

一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。
现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1万多。

乐观锁与悲观锁

上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过了,则重新取出的被修改后的价格,150元,这样他会将120元存入数据库。
如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证最终的价格是120元。

模拟修改冲突

  • 数据库中增加商品表
CREATE TABLE product
(
    id      BIGINT(20)  NOT NULL COMMENT '主键ID',
    name    VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',
    price   INT(11)          DEFAULT 0 COMMENT '价格',
    version INT(11)          DEFAULT 0 COMMENT '乐观锁版本号',
    PRIMARY KEY (id)
);
  • 添加数据
INSERT INTO product (id, NAME, price) VALUES (1, '外星人笔记本', 100);
  • 添加实体
@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    private Integer version;
}
  • 添加mapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.study.demo.pojo.Product;

public interface ProductMapper extends BaseMapper<Product> {
}
  • 测试
@Test
public void test() {
    //小李查询商品价格
    Product productLi = productMapper.selectById(1);
    System.out.println("小李查询的商品价格:"+productLi.getPrice());
    //小王查询商品价格
    Product productWang = productMapper.selectById(1);
    System.out.println("小王查询的商品价格:"+productWang.getPrice());
    //小李将商品价格+50
    productLi.setPrice(productLi.getPrice()+50);
    productMapper.updateById(productLi);
    //小王将商品价格-30
    productWang.setPrice(productWang.getPrice()-30);
    productMapper.updateById(productWang);
    //老板查询商品价格
    Product productLaoban = productMapper.selectById(1);
    System.out.println("老板查询的商品价格:"+productLaoban.getPrice());
}

image

乐观锁实现流程

数据库中添加version字段
取出记录时,获取当前version

SELECT id,`name`,price,`version` FROM product WHERE id=1

更新时,version + 1,如果where语句中的version版本不对,则更新失败

UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND `version`=1

MybatisPlus实现乐观锁

修改实体类

import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;

@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version
    private Integer version;
}

添加乐观锁插件配置

@Configuration
@MapperScan("com.study.demo.mapper")
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

测试修改冲突

image

优化流程

@Test
public void test() {
    //小李查询商品价格
    Product productLi = productMapper.selectById(1);
    System.out.println("小李查询的商品价格:"+productLi.getPrice());
    //小王查询商品价格
    Product productWang = productMapper.selectById(1);
    System.out.println("小王查询的商品价格:"+productWang.getPrice());
    //小李将商品价格+50
    productLi.setPrice(productLi.getPrice()+50);
    productMapper.updateById(productLi);
    //小王将商品价格-30
    productWang.setPrice(productWang.getPrice()-30);
    int result = productMapper.updateById(productWang);
    if(result == 0){
        //操作失败,重试
        Product productNew = productMapper.selectById(1);
        productNew.setPrice(productNew.getPrice()-30);
        productMapper.updateById(productNew);
    }
    //老板查询商品价格
    Product productLaoban = productMapper.selectById(1);
    System.out.println("老板查询的商品价格:"+productLaoban.getPrice());
}

image

标签:MybatisPlus,实现,productLi,乐观,商品价格,version,productWang,productMapper,getPrice
From: https://www.cnblogs.com/yellow-mokey/p/17167264.html

相关文章

  • 【触想智能】工业平板电脑实现宽压工作的途径你知道吗?
    工业平板电脑是专为适应工业环境使用而生产的一种工业一体机电脑。工业平板电脑对使用环境要求是比较高的,比如防水防尘、防静电、抗干扰等,在一些特殊的环境下,工业平板......
  • 登录功能_实现_前台页面 与登录功能_姓名提示
    登录功能_实现_前台页面$(function(){//1.给登录按钮绑定点击事件$("#btn_sub").click(function(){//2.发......
  • vue中通过formData实现单个文件上传
    <el-imagestyle="width:70px;height:80px":src="imageUrl"></el-image><div><imgalt=""ref="img"/><inputtype="file"ref="file"@change=......
  • java后台实现反向代理
    背景A平台登录,需要打通B平台白话文:当A登录的之后,就默认B也登录了,但是不能做单点登录,因为不能修改B的代码,B是开源的,但是有开源协议,所以B的登录不能动。B系统是嵌入在A系......
  • Golang make和new的区别及实现原理详解
    在Go语言中,有两个比较雷同的内置函数,分别是new和make方法,二者都可以用来分配内存,那他们有什么区别呢?下面我们就从底层来分析一下二者的不同。感兴趣的小伙伴们可以参考......
  • vue中实现formData批量上传多个文件
    utils/formData.jsimportVuefrom'vue'importaxiosfrom'axios'/***多个二进制流附件以数组格式上传*@param{*}url请求接口路径*@param{*}params......
  • #yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-区块链概念和实现
    前言区块链是一种分布式数据库,使用密码学技术进行安全的数据记录和验证。它可以被用来创建可信赖的记录,并确保记录不可篡改。区块链的原理其实是一个又一个区块组成的链条......
  • 企业实现云原生这些工具很关键!
    近年来云原生是一个非常火的概念,也逐渐成为公司数字平台的基石。例如:目前主要集中在无状态的容器应用程序中,缺乏对完整云原生应用生态的支持;它主要是单一公共云或私有云环境......
  • Java魔法类之Unsafe(cas)底层实现
    一、JVM层在java.util.concurrent包下面的很多类为了追求性能都采用了sun.misc.Unsafe类中的CAS操作,从而避免使用synchronized等加锁方式带来性能上的不足。在sun.misc.U......
  • 接口的定义与实现
    接口的定义与实现packagecom.andy.base.oop.demo01.demo09;publicinterfaceTimeService{voidtimer();}packagecom.andy.base.oop.demo01.demo09;//抽......