乐观锁
# 使用场景
- 解决丢失更新问题
- 当多个线程操作同一条记录时,需要更新的是上一个线程更新后的记录,否则会丢失更新
- 实现线程安全的数据更新操作
# 如何解决
- 给每条记录添加version
- 每次更新时,携带version信息
- 执行更新时
set version = newVersion where version = oldVersion
1
- 如果version不正确,那么会更新失败
- 如果更新失败,可以指定重试策略
- 如一直重试
- 如间隔一段时间重试一定次数,如果依然失败返回失败提示
- 如果更新失败,可以指定重试策略
# 使用乐观锁
- 修改user表,添加version列
alter table user
add version int null;
1
2
2
- 在实体类User上添加
@version
注解,以及字段
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
1
2
3
2
3
- 配置执行乐观锁的MybatisPlus实现的插件对象
- 创建配置类MybatisPlusConfig
- 注意:可以将启动类的MapperScan的配置移动到此处进行配置
package com.stt.demo.mybatisplus.config;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.stt.demo.mybatisplus.mapper")
public class MybatisPlusConfig {
// 乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 配置自动填充类,乐观锁的version创建时添加默认值
package com.stt.demo.mybatisplus.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class AppMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
// 添加对version的支持
this.setFieldValByName("version", 1, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 测试,先查询,再插入,观察version值的变化
@Test
public void testOptimisticLocker() {
User user = userMapper.selectById(1463512055645134850L);
user.setName("stt2");
userMapper.updateById(user);
}
1
2
3
4
5
6
2
3
4
5
6
Last Updated: 2022/01/16, 11:29:51