【Mybatis-Plus进阶学习(四)】乐观锁
什么时乐观锁?
第一步,先取出记录,获取当前version;第二步,当更新时,带上这个version;第三步:版本正确更新成功,错误更新失败。
示例:
update user set name = '向南天,version =3 where id = 1094592041087729777 and version = 2
乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。
- 乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。
- 悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。
所以悲观锁用于多写的情况,防止出现同时修改的问题,而乐观锁用于多读的情况,不上锁可以增加资源的利用。
乐观锁的简单使用
第一步:配置乐观锁拦截器
@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 不能复用的原因。