如果关键表没有加锁,则多个线程对同一条记录进行操作的时候,就会重复操作
加锁之后可以避免这个问题
加锁前:
如果有两个线程同时分别执行这两个语句,结果name 可能是coding1 也可能是 coding2,而且还会存在覆盖的情况,两个sql都执行成功了
update `id_info_2` set `name` = 'coding1' where id = 1 ;
update `id_info_2` set `name` = 'coding2' where id = 1 ;
加锁后:
如果有两个线程同时分别执行这两个语句,结果name 可能是coding1 也可能是 coding2,只有一个sql执行成功,另一个执行失败。(先执行的成功,后执行的失败)
update `id_info_2` set `name` = 'coding1' , `version` = `version` + 1 where id = 1 and `version` = 1;
update `id_info_2` set `name` = 'coding2' , `version` = `version` + 1 where id = 1 and `version` = 1;
在数据表中增加version字段
在表中新增int类型的version字段,默认值为1.
1. 插件配置
- 新增一个config
- 在这个config中启用乐观锁
- 使用EnableTransactionManagement注解,使程序可以提交事务
- 在启动类里面移除MapperScan注解
- 在config中使用MapperScan注解
@EnableTransactionManagement
@Configuration
@MapperScan("top.willnew.tools.user.mapper")
public class MybatisPlusConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
2. 修改实体类,新增@Version注解
@Version
private Integer version;
特别说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
网友评论