其实乐观锁很常用不要觉得很难似的,一步步来试一下

乐观锁先修改,更新的时候发现数据已经变了就回滚(check and set),乐观锁一般通过版本号或者时间戳实现。

这里我们使用Mybatis-Plus来进行使用

一.方法一使用 @Version 注解来实现

1.首先你要在你的表中添加一个字段这里我就定义为version用来控制版本

特别注意:

支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime

乐观锁 mysql 处理 乐观锁mybatis_java

 2.接着你需要在你这个表的实体类中添加

@Version:可以在实体 bean 中使用@Version 注解,通过这种方式可添加对乐观锁定的支持 一个类中只能有一个@Version注解 注意此属性 不能用 String

@Version
 private Integer version;

 3.在Application容器创建Bean(很重要否则会提示找不到)

@Bean
public MybatisPlusInterceptor myOptimisticLockerInnerInterceptor(){
     MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
     interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
     return interceptor;

 }

 4.最后这里贴一下我的业务处理代码吧,这就灵活使用了

@Override
public CommonResponse buyOne() {

    GoodsInfo goodsInfo = goodsInfoMapper.selectById(1);

    Integer inventoryNum = goodsInfo.getInventoryNum();
    if (inventoryNum <= 0){
        log.error("没有库存了!当前仓库为:"+inventoryNum);
        return CommonResponseUtils.dataIsNullError("没有库存了!");
    }

    int newInventoryNum= inventoryNum - 1;//修改库存
    goodsInfo.setInventoryNum(newInventoryNum);

    int update = goodsInfoMapper.updateById(goodsInfo);//更新
    if (update==1){
         log.info("下单成功!当前仓库为:"+newInventoryNum);
         return CommonResponseUtils.success("下单成功!当前仓库为:"+newInventoryNum);
    }
        log.error("下单失败!当前仓库为:"+newInventoryNum);
        return CommonResponseUtils.dataIsNullError("下单失败!当前仓库为:"+newInventoryNum);
}

 5.先看下我的数据库现在的库存5个

乐观锁 mysql 处理 乐观锁mybatis_乐观锁_02

 

 6.然后我用20的并发来测试看看,成功5个其他失败

乐观锁 mysql 处理 乐观锁mybatis_开发语言_03

 再看下数据库,好了很成功!

乐观锁 mysql 处理 乐观锁mybatis_ide_04

 二.其实原理还是依旧遵循

乐观锁是先修改,更新的时候发现数据已经变了就回滚

我们不使用方法一的@Version,这次相当于自己实现

这里我们就主要靠业务代码来实现了

思路:首先拿到一个库存数量 例如5,更新的时候一定要增加更新条件,那就是只有当前库存是5的时候才可以更新成功。(弊端1:失败次数多,2:如果有人增加库存那么的话。但是还是建议使用version方法一)

@Override
    public CommonResponse buyOne() {
        //查询商品
        GoodsInfo goodsInfo = goodsInfoMapper.selectById(1);
        //检测库存数量
        Integer inventoryNum = goodsInfo.getInventoryNum();//当前库存数量
        if (inventoryNum <= 0){
            log.error("没有库存了!当前仓库为:"+inventoryNum);
            return CommonResponseUtils.dataIsNullError("没有库存了!");
        }

        int newInventoryNum= inventoryNum - 1;//修改库存
        goodsInfo.setInventoryNum(newInventoryNum);

        QueryWrapper<GoodsInfo> query = Wrappers.query();
        query.eq("inventory_num",inventoryNum);

        int update = goodsInfoMapper.update(goodsInfo,query);//更新
        if (update==1){
            log.info("下单成功!当前仓库为:"+newInventoryNum);
            return CommonResponseUtils.success("下单成功!当前仓库为:"+newInventoryNum);
        }
        log.error("下单失败!当前仓库为:"+newInventoryNum);
        return CommonResponseUtils.dataIsNullError("下单失败!当前仓库为:"+newInventoryNum);
    }