先来看以下场景:
假设张三和李四都可以对某条记录进行操作,原始记录为(sex,age) = (‘male’, 25)。但在张三正在查询和修改数据时,李四率先完成了修改。所以张三提交时会导致李四的更新丢失,而张三却并不知情。
为了避免造成这种情况发生,MyBatis-Plus为我们实现了版本控制。
版本控制,顾名思义,就是在修改完数据时会更新一次数据的版本。如果读取时的版本和修改时的版本不一致,就不能执行更新操作。
如张三首先读到的 记录为(‘male’, 25),这是版本1。李四读取并修改为(‘male’, 30),此时该记录的版本变为2,而张三想要更新时发现最新版本与读取时版本不一致,那么就不能更新该记录。
这就是“乐观锁”的思想,版本控制是实现“乐观锁”最常用的方法。
乐观锁实现方式:
1、取出记录时,获取当前version
2、更新时,带上这个version
3、执行更新时, set version = newVersion where version = oldVersion
4、如果version不对,就更新失败
接下来介绍如何在Mybatis-Plus项目中,使用乐观锁:
1、修改实体类,添加version字段
@Version
private Integer version;
2、创建配置文件
创建包config,创建文件MybatisPlusConfig.java
此时可以删除主类中的 @MapperScan 扫描注解
@Configuration
@MapperScan("com.smallorange.mapper")
public class MybatisPlusConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
3、注册乐观锁插件
MP版本在3.3.x及以下的写法如下:
/**
* 乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
3.4及以上的写法如下:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
// mp插件接口
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
并在MyMetaObjectHandler中的insertFill()方法中添加自动填充
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("开始创建时间字段...");
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
this.setFieldValByName("version",1,metaObject);//记录的起始版本为1
}
4.测试
首先给数据库添加一条新记录
@Test
public void testAdd() {
User user = new User();
user.setName("SmallOrange");
user.setAge(22);
user.setEmail("1719302525@qq.com");
int insert = userMapper.insert(user);
System.out.println(insert);
}
插入成功,版本号自动填充为1
接着修改该条记录时,MP会自动将版本号加1,无需通过手动的方式用getVersion()方法得到version值再加1改版本号。
@Test
public void updateUser(){
User user = userMapper.selectById(35L);
user.setName("BigOrange");
int count=userMapper.updateById(user);
System.out.println(count);
}