实现思路如下:
- 取出当前需要更新的记录,获取当前version
- 更新时where语句中添加version = #{version}的语句,若携带的version和当前的version不相等,则失败。
- 更新成功后version+1,语句如下:
set version = newVersion where version = oldVersion
1.Mybatis实现
1)准备
- 向表中添加version字段
- 建立version的pojo模板,其中包括了表的主键,新的version值,旧的version值(供修改成功后使用)
//其实可以匹配完成之后,在修改时版本号直接+1,但如果担心这样做会使版本号溢出,则可以选择上面的方式
2)实施
- 修改字段时,判断一下获取的version字段是否与当前相等(where中添加version = #{version}的条件)
- 修改完成后修改版本号
- 可以在修改字段时直接传入+1的版本号
- 可以在修改完成后设置新的版本号
2.MybatisPlus实现
1)添加乐观锁的全局配置
/**
* 配置mybatis-plus拦截器
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
2)在实体类上添加@Version注解,开启乐观锁
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@TableName("product")
public class Product{
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private Long goodId;
private String goodName;
private Long goodNum;
@Version
private Integer version;
}
3.书写逻辑
下面是逻辑模拟,实现一种简单的并发效果
@Override
public Boolean updateProduct(Product product) {
QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
productQueryWrapper.eq("id", 1L);
Product productA = productMapper.selectOne(productQueryWrapper);
Product productB = productMapper.selectOne(productQueryWrapper);
productA.setGoodNum(productA.getGoodNum() + 50);//库存加50
productB.setGoodNum(productB.getGoodNum() - 30);//同时库存减去30
//更新库存
productMapper.updateById(productA);
int result = productMapper.updateById(productB);
if (result == 0) {
Product productC = productMapper.selectOne(productQueryWrapper);
productC.setGoodNum(productC.getGoodNum() - 30);
productMapper.updateById(productC);
}
return true;
}
本人小白,敬请各位大神指正