【黑马点评-3秒杀优惠券】一、单体秒杀初始逻辑(不考虑加锁)

涉及的表

tb_voucher:优惠券的基本信息,优惠金额、使用规则等
tb_seckill_voucher:优惠券的库存、开始抢购时间,结束抢购时间。特价优惠券才需要填写这些信息

  • voucher_id 主键 关联的优惠券...
  • stock 库存
  • create time 创建时间
  • begin time 生效时间
  • end time 失效时间
  • update time 更新时间

tb_voucher_order

代码逻辑

1. 查询优惠券信息,并通过数据库里的seckillvoucher的表的字段判断时间等

  1. SeckillVoucher 这个实体对应tb_seckill_voucher 表,通过实现了IService接口的类自动拥有了getById()方法,返回一个实体类。
  2. 使用MyBatis自动生成的 getter 方法,进行三个字段的比对
//     1. 查询优惠券信息
SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
//     2. 判断秒杀是否开始
if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
	return Result.fail("秒杀尚未开始");
}
// 3. 判断秒杀结束了么
if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
	return Result.fail("秒杀已经结束");
}
//     4. 判断库存还有么
if (voucher.getStock() < 1) {
	return Result.fail("库存不够了");
}

2. 通过链式更新

  1. 使用MyBatis-Plus的update方法,更新符合条件的记录
  2. 内置参数为一个实体对象封装操作类Wrapper
  3. 调用eq语句,找到符合的那个字段的记录
  4. 使用条件构造器的setSql方法,更新
boolean flag = seckillVoucherService.update(new LambdaUpdateWrapper<SeckillVoucher>().eq(SeckillVoucher::getVoucherId, voucherId).setSql("stock=stock-1"));

3. 创建对应的Voucher实体,保存到数据库中。

  1. 创建优惠券订单实体
  2. 然后生成一个uuid的优惠券id作为主键
  3. 设置userId
  4. 设置购买的voucherId
// 6. 秒杀成功,创建对应的订单,保存到数据库中
VoucherOrder voucherOrder = new VoucherOrder();
long orderId = redisIdWorker.nextId("seckill_voucher_order");
voucherOrder.setId(orderId);
voucherOrder.setUserId(UserHolder.getUser().getId());
voucherOrder.setVoucherId(voucherId);
flag = this.save(voucherOrder);

示例代码

/**
 * 1. 实现优惠券秒杀的下单功能(不考虑冲突)
 */
public Result seckillVoucher1(Long voucherId) {
    // 1. 查询优惠券信息
    SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
    // 2. 判断秒杀是否开始
    if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
        return Result.fail("秒杀尚未开始");
    }
    // 3. 判断秒杀结束了么
    if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
        return Result.fail("秒杀已经结束");
    }
    // 4. 判断库存还有么
    if (voucher.getStock() < 1) {
        return Result.fail("库存不够了");
    }
    // 5. 秒杀券合法,则秒杀券抢购成功,库存数量-1
    boolean flag = seckillVoucherService.update(new LambdaUpdateWrapper<SeckillVoucher>()
            .eq(SeckillVoucher::getVoucherId, voucherId).setSql("stock=stock-1"));
    if (!flag) {
        throw new RuntimeException("秒杀券扣减失败");
    }
    // 6. 秒杀成功,创建对应的订单,保存到数据库中
    VoucherOrder voucherOrder = new VoucherOrder();
    long orderId = redisIdWorker.nextId("seckill_voucher_order");
    voucherOrder.setId(orderId);
    voucherOrder.setUserId(UserHolder.getUser().getId());
    voucherOrder.setVoucherId(voucherId);
    flag = this.save(voucherOrder);
    if (!flag) {
        throw new RuntimeException("创建秒杀券订单失败");
    }
    return Result.ok(orderId);
}
posted @ 2025-04-15 12:38  kuki'  阅读(84)  评论(0)    收藏  举报