zoukankan      html  css  js  c++  java
  • 【Mybatis-Plus进阶学习(四)】乐观锁

    什么时乐观锁?
    第一步,先取出记录,获取当前version;第二步,当更新时,带上这个version;第三步:版本正确更新成功,错误更新失败。

    示例:
    update user set name = '向南天,version =3 where id = 1094592041087729777 and version = 2

    乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。

    • 乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。
    • 悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。

    来自【BAT面试题系列】面试官:你了解乐观锁和悲观锁吗?

    所以悲观锁用于多写的情况,防止出现同时修改的问题,而乐观锁用于多读的情况,不上锁可以增加资源的利用。

    乐观锁的简单使用

    第一步:配置乐观锁拦截器

        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor() {
            return new OptimisticLockerInterceptor();
        }
    

    第二步:在更新前先查询版本号,之后在更新时带上版本号作为查询判断条件

        @Test
        public void modifyById() {
            //查出原来的Version
            int version = userMapper.selectById(1094592041087729666L).getVersion();
            //修改
            User user = new User();
            user.setId(1094592041087729666L);
            user.setEmail("wsd@163.com");
            //设置版本号
            user.setVersion(version);
            int row = userMapper.updateById(user);
            System.out.println("影响的行数:" + row);
        }
    

    结果如下

    MP会自动将设置的版本号作为查询条件连接在SQL语句后面,然后将版本号+1再重新设置进数据库。

    注意事项

    这是官方就乐观锁给出的说明

    关于官方提示的最后一点,请看:

            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name", "刘红雨");
            //查出原来的Version
            int version = userMapper.selectById(1094592041087729666L).getVersion();
            //修改
            User user = new User();
            user.setEmail("wsd1@163.com");
            //设置版本号
            user.setVersion(version);
            int row = userMapper.update(user,queryWrapper);
            System.out.println("影响的行数:" + row);
    
    
            int version2 = userMapper.selectById(1094592041087729666L).getVersion();
            //修改
            User user2 = new User();
            user2.setEmail("wsd1@163.com");
            //设置版本号
            user2.setVersion(version2);
            //复用Query
            int row2 = userMapper.update(user2,queryWrapper);
            System.out.println("影响的行数:" + row2);
    

    两个同样的修改,但是使用了同一个Wrapper,接下来,我们看看结果

    可以看出第一个更新十分正常,但是第二个更新的时候条件出现了两个Version,这就是为什么在 update(entity, wrapper)方法下, wrapper 不能复用的原因。

  • 相关阅读:
    设计模式 对象结构型 代理模式
    设计模式 对象/类结构型 适配器模式
    设计模式 创建型 原型模式
    设计模式 创建型 建造模式
    Django REST framework使用及源码分析之权限
    Django REST framework使用及源码分析之验证
    某游戏公司运维开发python笔试题
    django中间件的5个方法以及csrf的装饰器用法
    Django源码理解一
    消息中间件-RabbitMQ
  • 原文地址:https://www.cnblogs.com/zllk/p/14239765.html
Copyright © 2011-2022 走看看