一人一单问题
java
运行
// 1. 获取当前登录的用户ID Long userId = UserHolder.getUser().getId();
UserHolder:保存当前登录用户信息的工具类- 这行就是拿到:是谁在下单
- 比如:用户 id = 101
java
运行
// 2. 去数据库订单表里查:
// 条件1:用户id = 当前登录用户
// 条件2:优惠券id = 这次要抢的券
int count = query()
.eq("user_id", userId) // 这个用户
.eq("voucher_id", voucherId) // 这个优惠券
.count(); // 统计有几条订单记录
翻译成人话:
“去订单表里查一查,用户 101 有没有买过 优惠券 1001?
买过几次?把次数给我统计出来!”
count就是购买次数- 没买过 → count = 0
- 买过 → count = 1 或更多
java
运行
// 3. 如果购买次数 > 0,说明已经买过了,直接拒绝
if (count > 0) {
return Result.fail("用户已经购买过一次!");
}
- 如果 count > 0 → 买过 → 拦截,不让买
- 如果 count = 0 → 没买过 → 放行,继续下单
用生活例子讲明白
你去买限量优惠券:
- 系统先看你是谁(拿用户 ID)
- 去订单本里翻:你有没有买过这张券?
- 买过 → 告诉你:不行,一人只能买一次
- 没买过 → 可以继续下单
这就是 一人一单!
核心原理总结(3 句话背会)
- 拿到当前用户 ID
- 查数据库:这个用户 + 这个券 → 有没有订单?
- 有就拦截,没有就放行
⚠️ 重要提醒(面试 / 高并发必问)
你现在这段代码 单机没问题,
但高并发下会失效!会出现一人买多单!
为什么?
- 两个请求同时进来
- 同时查数据库,都查到 count=0
- 同时通过判断
- 最后都下单成功
解决办法:加锁(分布式锁)
让同一个用户的请求,只能一个一个排队判断,就不会重复下单了。
