Home Springboot功能模块 乐观锁解决超卖

乐观锁解决超卖

使用同步代码块,效率低下,因此改为乐观锁

 

StockMapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.southwind.mmall002.mapper.StockMapper">


    <!--根据商品 ID 扣除库存-->
    <update id="updateSale" parameterType="com.southwind.mmall002.entity.kill.Stock">
        update stock
        set
            saled=saled + 1,
            version = version + 1
        where
            id = #{id}
            and
            version = #{version}
    </update>
</mapper>

Service层代码
    public  Integer kill(Integer id, HttpSession session) {
        //根据 商品 ID 校验库
        Stock stock = checkStock(id);
        LOGGER.info("商品的名称为:" + stock.getName());
        LOGGER.info("商品的已售为:" + stock.getSaled());
        LOGGER.info("商品的库存为:" + stock.getCount());
        //更新库存
        updateSale(stock);
        //创建订单
        return createOrder(stock,session);
    }

    //校验库存
    private Stock checkStock(Integer id){
        Stock stock = stockMapper.selectById(id);
        if(stock.getSaled().equals(stock.getCount())){
            throw new RuntimeException("库存不足!!!");
        }
        return stock;
    }

    //扣除库存
    private void updateSale(Stock stock){
        LOGGER.info("准备更新库存...");
        //在 SQL 层面完成销量的+1 和 版本号的+1 并且根据商品 ID 和版本号同时查询更新的商品
        stock.setSaled(stock.getSaled() + 1);
        int updateRows = stockMapper.updateSale(stock);//返回更新的条数
        if(updateRows == 0 ){
            throw new RuntimeException("抢购失败,请重试!!!");
        }
    }

    //创建订单
    private Integer createOrder(Stock stock,HttpSession session){
        User user= (User) session.getAttribute("user");
        Orders orders = new Orders();
        orders.setUserId(user.getId());
        orders.setLoginName(user.getLoginName());
        orders.setSerialnumber(stock.getName());
        orderMapper.insert(orders);
        return orders.getId();
    }

}

结果:实现了线程同步

SIMILAR ARTICLES

发表评论

发表评论