美文网首页
秒杀第十三节:交易模型管理-交易模型创建

秒杀第十三节:交易模型管理-交易模型创建

作者: 小石读史 | 来源:发表于2020-08-14 10:47 被阅读0次

    首先创建用户下单的交易模型

    @Data
    public class OrderModel {
        //要用string
        private String id;
    
        private Integer userId;
    
        private Integer itemId;
    
        private BigDecimal itemPrice;
    
        private Integer amount;
    
        private BigDecimal orderPrice;
    
    }
    

    创建订单表并初始化部分数据用于测试

    DROP TABLE IF EXISTS `order_info`;
    
    CREATE TABLE `order_info` (
      `id` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
      `user_id` int(11) NOT NULL DEFAULT '0',
      `item_id` int(11) NOT NULL DEFAULT '0',
      `item_price` decimal(10,2) NOT NULL DEFAULT '0.00',
      `amount` int(11) NOT NULL DEFAULT '0',
      `order_price` decimal(10,2) NOT NULL DEFAULT '0.00',
      `promo_id` int(11) NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    
    /*Data for the table `order_info` */
    
    insert  into `order_info`(`id`,`user_id`,`item_id`,`item_price`,`amount`,`order_price`,`promo_id`) values 
    ('2019041000000000',9,36,6999.00,1,6999.00,0),
    ('2019041000000100',9,36,6999.00,1,6999.00,0),
    ('2019041000000200',9,36,6999.00,1,6999.00,0),
    ('2019041200000300',9,40,200.00,1,200.00,2);
    

    修改pom.xml将允许自动覆盖文件改为false,然后修改mybatis-generator.xml中的表为order_info,最后使用mybatis自动生成器生成基础服务。使用方式在秒杀第三节有说明
    生成mapper文件和DO文件后新增OrderService类

    public interface OrderService {
    
        //1.通过前端url上传过来秒杀活动id,然后
        //2.直接在下单接口内判断对应商品是否在秒杀
        OrderModel createOrder(Integer userId, Integer itemId,Integer amount) throws BussinessException;
    }
    

    实现OrderService 中的创建订单方法。创建订单分为以下几步:
    1.校验下单状态(用户是否合法,下单商品是否存在,购买数量是否正确)
    2.落单减库存
    3.订单入库(生成交易流水号,订单号)
    4.商品销量增加
    5.返回前端
    代码实现
    首先在itemService中定义落单减库存和商品下单后对应销量增加接口

    //库存扣减
     boolean decreaseStock(Integer itemId,Integer amount);
    
     //商品下单后对应销量增加
     void increaseSales(Integer itemId,Integer amount) throws BussinessException;
    

    在ItemServiceImpl中实现itemService中的落单减库存和商品下单后对应销量增加接口

    @Override
        @Transactional
        public boolean decreaseStock(Integer itemId, Integer amount) {
    
            int affectedRow = itemStockDOMapper.decreaseStock(itemId,amount);
            if(affectedRow > 0){
                return true;
            }else {
                return false;
            }
        }
    
        @Override
        @Transactional
        public void increaseSales(Integer itemId, Integer amount) throws BussinessException {
            itemDOMapper.increaseSales(itemId,amount);
    
        }
    

    然后在对应itemStockDOMapper和itemDOMapper中实现落单减库存和商品下单后对应销量增加

    int increaseSales(@Param("id")Integer id, @Param("amount")Integer amount);
    int decreaseStock(@Param("itemId") Integer itemId, @Param("amount") Integer amount);
    
    <update id="increaseSales">
    update item
    set sales = sales + #{amount}
    where id = #{id,jdbcType=INTEGER}
    </update>
    
    <update id="decreaseStock">
    update item_stock
    set stock = stock - #{amount}
    where item_id = #{itemId} and stock >= #{amount}
    </update>
    

    在订单入库的时候一般会生成交易流水号和订单号,订单号有16位,中间六位为自增序列,最后两位分库分表位
    因为中间六位为自增序列,我们会设计一个表sequence_info来获取当前sequence,表结构如下:

    DROP TABLE IF EXISTS `sequence_info`;
    
    CREATE TABLE `sequence_info` (
      `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
      `current_value` int(11) NOT NULL DEFAULT '0',
      `step` int(11) NOT NULL DEFAULT '0',
      PRIMARY KEY (`name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    
    /*Data for the table `sequence_info` */
    
    insert  into `sequence_info`(`name`,`current_value`,`step`) values 
    ('order_info',4,1);
    

    修改pom.xml将允许自动覆盖文件改为false,然后修改mybatis-generator.xml中的表为sequence_info,最后使用mybatis自动生成器生成基础服务。使用方式在秒杀第三节有说明
    OrderServiceImpl实现创建订单

    @Service
    public class OrderServiceImpl implements OrderService {
    
        @Autowired
        private ItemService itemService;
        @Autowired
        private UserService userService;
    
        @Autowired
        private OrderDOMapper orderDOMapper;
    
        @Autowired
        private SequenceDOMapper sequenceDOMapper;
    
        @Override
        @Transactional
        public OrderModel createOrder(Integer userId, Integer itemId,Integer amount) throws BussinessException {
            //1.校验下单状态(用户是否合法,下单商品是否存在,购买数量是否正确)
            ItemModel itemModel = itemService.getItemById(itemId);
            if(itemModel == null) {
                throw new BussinessException((EmBusinessError.PARAMETER_VALIDATION_ERROR),"商品不存在");
            }
            UserModel userModel = userService.getUserById(userId);
            if(userId == null) {
                throw new BussinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"用户不存在");
            }
            if(amount <= 0 || amount > 99){
                throw new BussinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"数量信息不正确");
            }
    
    
            //2.落单减库存,
            boolean result = itemService.decreaseStock(itemId,amount);
            if(!result) {
                throw new BussinessException(EmBusinessError.STOCK_NOT_ENOUGH);
            }
    
            //3.订单入库
            OrderModel orderModel = new OrderModel();
            orderModel.setUserId(userId);
            orderModel.setItemId(itemId);
            orderModel.setAmount(amount);
            orderModel.setItemPrice(itemModel.getPrice());
            orderModel.setOrderPrice(orderModel.getItemPrice().multiply(BigDecimal.valueOf(amount)));
    
            //生成交易流水号,订单号
            orderModel.setId(generatorOrderNo());
            OrderDO orderDO = convertFromOrderModel(orderModel);
            orderDOMapper.insertSelective(orderDO);
            //商品销量增加
            itemService.increaseSales(itemId,amount);
            //返回前端
            return orderModel;
        }
    
    
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        String generatorOrderNo(){
            //1.订单号有16位
            StringBuilder stringBuilder = new StringBuilder();
            //前8位为时间信息,年月日
            LocalDateTime now = LocalDateTime.now();
            String nowDate = now.format(DateTimeFormatter.ISO_DATE).replace("-","");
            stringBuilder.append(nowDate);
    
            //2.中间六位为自增序列
            //获取当前sequence
            int sequence = 0;
            SequenceDO sequenceDO = sequenceDOMapper.selectByPrimaryKey("order_info");
            sequence = sequenceDO.getCurrentValue();
            sequenceDO.setCurrentValue(sequenceDO.getCurrentValue()+sequenceDO.getStep());
            sequenceDOMapper.updateByPrimaryKeySelective(sequenceDO);
            //凑足六位
            String sequenceStr = String.valueOf(sequence);
            for(int i = 0; i < 6 - sequenceStr.length(); i++) {
                stringBuilder.append(0);
            }
            stringBuilder.append(sequenceStr);
    
            //3.最后两位分库分表位
            stringBuilder.append("00");
            return stringBuilder.toString();
        }
        private OrderDO convertFromOrderModel(OrderModel orderModel){
            if(orderModel == null){
                return null;
            }
            OrderDO orderDO = new OrderDO();
            BeanUtils.copyProperties(orderModel,orderDO);
            return orderDO;
        }
    }
    

    OrderController封装下单

    @Controller("/order")
    @RequestMapping("/order")
    @CrossOrigin(origins = {"*"}, allowCredentials = "true")
    public class OrderController extends BaseController {
    
        @Autowired
        private OrderService orderService;
    
        @Autowired
        private HttpServletRequest httpServletRequest;
    
        //封装下单请求
        @RequestMapping(value = "/createorder", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
        @ResponseBody
        public CommonReturnType createOrder(@RequestParam(name="itemId")Integer itemId,
                                            @RequestParam(name="promoId",required = false)Integer promoId,
                                            @RequestParam(name="amount")Integer amount) throws BussinessException {
    
            //获取登录信息(Boolean)
            Boolean isLogin = (Boolean) this.httpServletRequest.getSession().getAttribute("IS_LOGIN");
            if(isLogin == null || !isLogin.booleanValue()){
                throw new BussinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆,不能下单");
            }
            UserModel userModel = (UserModel) this.httpServletRequest.getSession().getAttribute("LOGIN_USER");
            OrderModel orderModel = orderService.createOrder(userModel.getId(),itemId,amount);
            return CommonReturnType.create(null);
    
        }
    
    }
    

    下单测试参数:http://localhost:8080/order/createorder?itemId=41&amount=2
    结果:

    image.png

    相关文章

      网友评论

          本文标题:秒杀第十三节:交易模型管理-交易模型创建

          本文链接:https://www.haomeiwen.com/subject/tdspdktx.html