服务端实现秒杀简单实例(单应用)

1.数据库表

a.库存表

CREATE TABLE `stock` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
  `count` int(11) NOT NULL COMMENT '库存',
  `sale` int(11) NOT NULL COMMENT '已售',
  `version` int(11) NOT NULL COMMENT '乐观锁,版本号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

b.订单表

CREATE TABLE `stock_order` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `sid` int(11) NOT NULL COMMENT '库存ID',
  `name` varchar(30) NOT NULL DEFAULT '' COMMENT '商品名称',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1072 DEFAULT CHARSET=utf8
2.订单服务类
package com.allen.modules.api.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.allen.modules.api.bo.OrderInfo;
import com.allen.modules.api.dao.StockMapper;
import com.allen.modules.api.dao.StockOrderMapper;
import com.allen.modules.api.po.Stock;
import com.allen.modules.api.po.StockOrder;

@Service
@Transactional
public class OrderInfoService {
    
    @Resource
    private StockMapper stockMapper;
    
    @Resource
    private StockOrderMapper stockOrderMapper;
    
    /**
     * 下单服务
     */
    public Integer createOrder(Integer sid){
        //检查库存
        Stock stock=this.checkStock(sid);
        
        //扣减库存
        //this.saleStock(stock);
        
        //扣减库存(乐观锁)(防止超卖)
        this.saleStockByCAS(stock);

        //下单
        return this.newOrder(stock);
    }
    
    /**
     * 检查库存
     */
    public Stock checkStock(Integer sid){
        Stock stock=this.stockMapper.selectByPrimaryKey(sid);
        if(stock.getCount().compareTo(stock.getSale())<=0){
            throw new RuntimeException("库存不足!");
        }
        return stock;
    }
    
    /**
     * 扣减库存(常规方式,会出现超卖情况)
     */
    public void saleStock(Stock stock){
        Stock updateEntity=new Stock();
        updateEntity.setSale(stock.getSale()+1);
        updateEntity.setId(stock.getId());
        this.stockMapper.updateByPrimaryKeySelective(updateEntity);
    }
    
    /**
     * 扣减库存(乐观锁)
     */
    public void saleStockByCAS(Stock stock){
        Stock updateEntity=new Stock();
        updateEntity.setSale(stock.getSale()+1);
        updateEntity.setId(stock.getId());
        updateEntity.setVersion(stock.getVersion());
        int count=this.stockMapper.updateByCAS(updateEntity);
        if(count==0)
            throw new RuntimeException("并发更新失败!");
    }
    
    /**
     * 下单
     */
    public Integer newOrder(Stock stock){
        StockOrder order=new StockOrder();
        order.setSid(stock.getId());
        order.setName(stock.getName());
        order.setCreateTime(new Date());
        return this.stockOrderMapper.insertSelective(order);
    }
}
3.库存持久化类
package com.allen.modules.api.dao;

import com.allen.modules.api.po.Stock;

public interface StockMapper {
    
    int deleteByPrimaryKey(Integer id);

    int insert(Stock record);

    int insertSelective(Stock record);

    Stock selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Stock record);

    int updateByPrimaryKey(Stock record);
    
    /**
     * 根据乐观锁更新
     */
    int updateByCAS(Stock record);
}
4.Mybatis乐观锁更新库存SQL

  
    update stock
    
      
        name = #{name,jdbcType=VARCHAR},
      
      
        count = #{count,jdbcType=INTEGER},
      
      
        sale = #{sale,jdbcType=INTEGER},
      
      version = version+1
    
    where id = #{id,jdbcType=INTEGER} and version = #{version,jdbcType=INTEGER}
  
5.API代码
    /**
     * 下单
     */
    @RequestMapping(value="/api/order/create",method=RequestMethod.POST)
    @ResponseBody
    public Result createOrder(@RequestBody CreateOrder request){
        return new Result<>(this.orderInfoService.createOrder(request.getSid()));
    } 






你可能感兴趣的:(服务端实现秒杀简单实例(单应用))