使用场景: 当要更新一条数据时,希望这条数据没有被别人更新,也就是说实现线程安全的数据更新
1. 数据库新增version字段, int类型, 默认值为0
2. 引入依赖
<!--mybatis拦截器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
3. springboot启动类中新增bean
/**
* 支持拦截器乐观锁
*
* @return
*/
@Bean
public MybatisPlusInterceptor optimisticLockerInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
4. 实体类 version字段贴上注解 @Version
@Version
private Long version;
5. sql更新语句 (更新操作version都会+1)
update wx_dept set name=#{name}, sn=#{sn}, version=#{version}+1 where id=#{id} and version=#{version}
6. service (乐观锁操作步骤: 每次操作前都是先查询、替换、最后更新, 否则乐观锁无效)
/**
* 修改部门
*
* @param wxDept 部门
* @return 结果
*/
@Override
public AjaxResult updateWxDept(WxDept wxDept) {
// 乐观锁操作步骤: 每次操作前都是先查询、替换、最后更新, 否则乐观锁无效
// 1. 先查询
WxDept dept = wxDeptMapper.selectWxDeptById(wxDept.getId());
log.info("查询出来的数据: {}", dept);
// 2. 替换
dept.setName("小卖铺");
dept.setSn("sell");
// 3. 最后更新
int i = wxDeptMapper.updateWxDept(dept);
if (i > 0) {
return AjaxResult.success("乐观锁更新成功");
} else {
return AjaxResult.error("乐观锁更新失败");
}
}
7. 测试
7.1 查询出id是1的数据, 并修改数据 name=小卖铺, sn=sell
查询出来的数据: com.ruoyi.ruoyiwx.dept.domain.WxDept@861f795[
id=1
name=开发部
sn=dev
version=0
]
7.2 假设7.1还没更新时, 就有其它线程修改了id为1的数据, 版本号version=1
7.3 上面7.1执行update更新时就会失败, 因为版本号version=1, 不是刚查询出来的version=0
{
"msg": "乐观锁更新失败",
"code": 500
}
总结:
1. 每次去拿数据的时候都会认为别人不会修改数据, 所以不会上锁 2. 但是在更新的时候会判断在此期间有没有人去更新过这个数据, 可以使用版本号version