首页 > 其他分享 >mybatisplus乐观锁(单个任务)

mybatisplus乐观锁(单个任务)

时间:2024-04-26 18:57:05浏览次数:19  
标签:Goods goods mybatisplus goodsDao 乐观 version 线程 更新 单个

乐观锁:在关系数据库管理系统里,乐观并发控制(又名“乐观锁”,Optimistic Concurrency Control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么会放弃修改。

简单来说,乐观锁主要解决的问题是当要更新一条记录的时候,希望这条记录没有被别人更新,如果别人更新了那么我就不更新了。

2.实现乐观锁的思路
乐观锁的实现方式:

数据库表中添加version列,比如默认值给1
第一个线程要修改数据之前,取出记录时,获取当前数据库中的version=1
第二个线程要修改数据之前,取出记录时,获取当前数据库中的version=1
第一个线程执行更新时,set version = newVersion where version = oldVersion
newVersion = version+1 [2] (表示更新后的值)
oldVersion = version [1] (表示取出记录时的值)
第二个线程执行更新时,set version = newVersion where version = oldVersion
newVersion = version+1 [2]
oldVersion = version [1]
假如这两个线程都来更新数据,第一个和第二个线程都可能先执行
假如第一个线程先执行更新,会把version改为2,
第二个线程再更新的时候,set version = 2 where version = 1,此时数据库表的数据version已经为2,所以第二个线程会修改失败
反之同理
不管谁先执行都会确保只能有一个线程更新数据,这就是MP提供的乐观锁的实现原理分析。

  

3.实现乐观锁的具体步骤

  1. 在数据库表上添加version列,我这里直接创建一个新表方便演示
    CREATE TABLE goods (
        id BIGINT(20) PRIMARY KEY AUTO_INCREMENT,
        NAME VARCHAR(32) NOT NULL,
        prices INT(10) NOT NULL ,
        `version` INT(10) NOT NULL DEFAULT 1
    );
    
    INSERT INTO goods VALUES(NULL,'book',10,1);
    INSERT INTO goods VALUES(NULL,'computer',3000,1);
    

      表的内容如下:

  2. 在模型类中添加对应的属性
    @Data
    public class Goods {
        /**
         * 实现id自增长
         */
        @TableId(type = IdType.AUTO)
        private Integer id;
        private String name;
        //标记此属性为version列对应的属性
        @Version
        private Integer version;
    }
    
  3. 添加乐观锁的拦截器
    @Configuration
    public class MybatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            //1 创建MybatisPlusInterceptor拦截器对象
            MybatisPlusInterceptor mpInterceptor=new MybatisPlusInterceptor();
            //2 添加乐观锁拦截器
            mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return mpInterceptor;
        }
    }
    
  4. 在测试类中执行更新操作
    @SpringBootTest
    class SpringBootMypatisPlusApplicationTests {
    
        @Autowired
        private GoodsDao goodsDao;
    
        @Test
        void test()
        {
            Goods goods = new Goods();
            goods.setId(1);
            goods.setPrices(100);
            goodsDao.updateById(goods);
        }
    }
    

      

     

    通过结果我们可以发现,我们创建的这个对象并没有设置version数据,所以也就没有更新version字段

    添加version数据

    @SpringBootTest
    class SpringBootMypatisPlusApplicationTests {
    
        @Autowired
        private GoodsDao goodsDao;
    
        @Test
        void test()
        {
            Goods goods = new Goods();
            goods.setId(1);
            goods.setVersion(1);
            goods.setPrices(100);
            goodsDao.updateById(goods);
        }
    }
    

      

     

    此时你可以发现,我们传递的是1,更新时会将version+1得到2,然后更新数据到数据库表里。

    此时我们需要注意的是,我们设置的version数据就相当于上面讲的oldVersion,如果和数据库表中的不同,则sql更新失败

    所以我们要想实现乐观锁,首先就是要得到表中要查找的那条数据的version,然后拿version当条件在将version加1更新回到数据库表中,所以我们在查询的时候,需要对其进行查询

    @SpringBootTest
    class SpringBootMypatisPlusApplicationTests {
    
        @Autowired
        private GoodsDao goodsDao;
    
        @Test
        void test()
        {
            //1.先通过要修改的数据id将当前数据查询出来
            //获得version字段值
            Goods goods = goodsDao.selectById(1);
            //2.修改数据
            goods.setPrices(200);
            goodsDao.updateById(goods);
        }
    }
    

      

     现在我们来模拟一遍秒杀的过程,看看多人修改同一商品的时候,是不是只能有一个人修改成功。

    @SpringBootTest
    class SpringBootMypatisPlusApplicationTests {
    
        @Autowired
        private GoodsDao goodsDao;
    
        @Test
        void test() {
            //1.先通过要修改的数据id将当前数据查询出来
            //获得version字段值
            Goods goods1 = goodsDao.selectById(1); // version = 3
            Goods goods2 = goodsDao.selectById(1); // version = 3
            //2.修改数据
            goods1.setPrices(1000);
            goodsDao.updateById(goods1);// 修改完后 version = 4
            goods2.setPrices(1000);
            goodsDao.updateById(goods2);// 此时 oldversion的值已经发生变化,不在等于3,所以修改失败
        }
    }
    

      

     

     

    原文链接:https://blog.csdn.net/weixin_53029342/article/details/125609830

标签:Goods,goods,mybatisplus,goodsDao,乐观,version,线程,更新,单个
From: https://www.cnblogs.com/xianz666/p/18160689

相关文章

  • MyBatisPlus乐观锁批量更新
    MyBatis-Plus提供了乐观锁插件 OptimisticLockerInterceptor 用于处理乐观锁,但是对于批量更新操作,乐观锁插件默认不会生效。要实现批量更新时的乐观锁控制,你需要自定义批量更新的逻辑。以下是一个自定义批量更新并使用乐观锁的示例:@ServicepublicclassYourService{......
  • SpringBoot+MyBatisPlus报错 Invalid value type for attribute 'factoryBeanObjectTy
    依赖版本org.springframework.boot:spring-boot-starter-web:3.2.5com.baomidou:mybatis-plus-boot-starter:3.5.5错误Invalidvaluetypeforattribute'factoryBeanObjectType'问题原因:这个问题是由于依赖传递导致,在MyBatis起步依赖中的myBatis-spring版本过低,导致程......
  • springboot+mybatisplus+dynicDatasource 从数据库表中查询数据源 动态添加
    1、pom依赖<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/><!--lookuppa......
  • FormData传输JSON同时上传单个/多个文件问题
    背景最近在开发一个功能时,涉及到向后端接口发送:JSON请求参数多个文件刚开始想通过RequestBody(application/json)形式进行传值,但是文件不好处理。有一个通过application/json传输文件数据的方法,就是将文件转成base64,然后在后端进行处理。但是这种方式涉及到大文件传输的时候,转......
  • mybatisplus分页中,模糊匹配一个字符串在列a或者列b下都可以筛选出的写法
    话不多说,直接上代码,and那句就对了LambdaQueryWrapper<类>wrapper=newLambdaQueryWrapper<类>().in(逻辑内容).like(正常逻辑内容).and(wrapperNew->wrapperNew.like(StringUtils.isNotEmpty(filter.getLocation()),......
  • mybatisplus常用写法
    一、QueryWrapper和LambdaQueryWrapper的区别写法和表达方式不同:QueryWrapper:使用传统的字符串形式构建查询条件,通过支持链式调用的方式,可以方便地拼接多个查询条件。LambdaQueryWrapper:使用Lambda表达式构建查询条件,可以通过实体类的属性和方法来安全地编写查询条件,减少犯......
  • mybatisplus
    官网啥都有https://baomidou.com/1.引入依赖<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency>2.定义Mapp......
  • mybatisplus
    mybatisplus如何实现获取信息通过扫描实体类并通过反射获取实体类信息作为数据库表信息约定:类名、变量名驼峰转下划线作为表名id字段默认为主键常用注解@TableName,@TableId,@TableField@TableField使用场景:成员变量为boolean并且名称为is开头,转化时会去掉is......
  • 80、SpringBoot3 SpringSecurity Mybatisplus最新版 整合 实现登入权限控制
    1、导入pom依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apac......
  • SpringBoot+MybatisPlus 增删改查学习第三章 (C#转JAVA)
    packagecom.example.demo;importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper;importcom.example.demo.entity.Person;importcom.example.demo.mapper.PersonMapper;importcom.example.demo.service.PersonService;importorg.junit.jupiter.api.Test;i......