SpringBoot构建电商基础秒杀项目知识点总结(第4-6章)


4-1 商品模型模型–商品创建01

1.模型设计

产品经理给到前端展示界面,得到要展示的view object之后,应该优先考虑领域模型,再考虑数据库表结构.(例如用户信息的的密码字段需要考虑分配在另一张表中,或者需要考虑领域模型中级联嵌套的关系)


此项目中,考虑到商品库存跟交易流水相关,将其分配在另一张表中,以便以后面的分库分表操作,性能优化和水平拆分.

销量字段在此项目中考虑只作用于展示,与商品信息放到一起.当用户发生交易行为后,通过异步的方式给销量值加1,而不会影响下单主链路

价格字段,在模型中采用BigDecimal类型,数据库中采用double类型.

4-2 商品模型模型–商品创建02

1.面向领域设计:所有的创建完成后都必须返回创建完成的对象实体,因为必须要让上游知道创建完成后的对象的状态.
2.在插入没有主键,需要数据库使用默认值和自增方式产生主键的对象后,会自动给该对象赋值主键.

4-4 商品模型模型–商品列表

1.使用Java8的stream API统一转换list

        //使用Java8的stream API
        List<ItemModel> itemModelList = itemDOList.stream().map(itemDO -> {
            ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(itemDO.getId());
            ItemModel itemModel = this.convertModelFromDataObject(itemDO, itemStockDO);
            return itemModel;
        }).collect(Collectors.toList());

4-5 商品模型模型–商品列表页面

如果不添加data-id域,在下面闭包中则无法反问其元素.
在这里插入图片描述

4-6 商品模型模型–商品详情页面

从url中取得元素的方法

    function getParam(paramName) {
        paramValue = "", isFound = !1;
        if (this.location.search.indexOf("?") == 0 && this.location.search.indexOf("=") > 1) {
            arrSource = unescape(this.location.search).substring(1, this.location.search.length).split("&"), i = 0;
            while (i < arrSource.length && !isFound)
                arrSource[i].indexOf("=") > 0 && arrSource[i].split("=")[0].toLowerCase() == paramName.toLowerCase() && (paramValue = arrSource[i].split("=")[1], isFound = !0), i++
        }
        return paramValue == "" && (paramValue = null), paramValue
    }

5-2 交易模型管理–交易下单01

1.落单减库存优于支付减库存
落单减库存:在创建订单之前将指定数量的库存锁定给该用户使用,能够保证用户支付后买到商品.
支付减库存:在创建订单之前只是确保有指定数量的库存,而不锁,等到支付过后才将库存扣减.无法保证用户不会超买商家的商品,需要走退款流程.只在商家未来保证用户交易率且有额外库存的情况下使用(避免用户恶意下单而不支付).
2.独立出来的商品库存表在某些高压的情况下可以做降级,专门独立出一个库存服务对其做减操作.而且减库存时,将会对商品库存表上行锁,分开设计表则不会影响商品表的查询性能.
3.数据库update时可将其返回值设为int,表示影响行数,从而判断逻辑上是否正确执行.(不需要update完再select,优化了查询)

5-3 交易模型管理–交易下单02

1.生成序列化订单号

(1) java8中有LocalDateTime,是吸收了joda-time方式并做了一套实现,依旧更建议使用jada-time.

    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.9.1</version>
    </dependency>

(2) select … for update 是为了在查询时,避免其他用户以该表进行插入,修改或删除等操作,造成表的不一致性.select查询是不加锁的,select…for update是会加锁的,而且是悲观锁.
在where 后面查询条件是主键索引,唯一索引时候是行锁
查询条件是普通字段时候加的是表锁

(3) mysql不像oracle可以获得一个自增序列,可以使用一张表来维护.

@Transactional(propagation = Propagation.REQUIRES_NEW)
    //不管该方法是否在事务中,都会开启一个新的事务,不管外部事务是否成功
    //最终都会提交掉该事务,为了保证订单号的唯一性,防止下单失败后订单号的回滚
    //下单是被也不应该再次使用失败的订单号
    private String generateOrderNo() {
        //订单有16位
        StringBuilder stringBuilder = new StringBuilder();
        //前8位为时间信息,年月日
        LocalDateTime now = LocalDateTime.now();
        String nowDate = now.format(DateTimeFormatter.ISO_DATE).replace("-", "");
        stringBuilder.append(nowDate);

        //中间6位为自增序列
        //获取当前sequence
        int sequence = 0;
        SequenceDO sequenceDO = sequenceDOMapper.getSequenceByName("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);

        //最后两位为分库分表位,暂时不考虑
        stringBuilder.append("00");

        return stringBuilder.toString();
    }

6-4 秒杀模型管理–活动模型与商品模型结合03

public interface OrderService {

    //1.通过url上传过来秒杀活动id,然后下单接口内校验对应id是否属于对应商品且活动已开始
    //2.直接在下单接口内判断对应的商品是否存在秒杀活动,若存在进行中的则以秒杀价格下单
    //倾向于使用第一种形式,因为对同一个商品可能存在不同的秒杀活动,而且第二种方案普通销售的商品也需要校验秒杀
    OrderModel createOrder(Integer userId, Integer itemId, Integer promoId, Integer amount) throws BusinessException;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值