【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 不能复用的原因。

原文地址:https://www.cnblogs.com/zllk/p/14239765.html