库存不足时应主动校验并抛出自定义异常InsufficientStockException,而非依赖数据库约束;该异常继承RuntimeException,含required/available字段,需在业务层查库后立即判断并抛出,由Controller统一捕获返回友好提示,确保事务回滚与日志记录。

库存不足时触发扣减失败,本质是业务校验不通过后主动抛出自定义异常,而非让程序崩溃。关键在于:先校验库存是否足够,不满足则立即抛出你定义的异常(如 InsufficientStockException),并确保上层能捕获、识别、正确处理它(比如回滚事务、返回友好提示)。
定义清晰的自定义异常类
继承 RuntimeException(非检查异常,调用方无需强制 try-catch,更符合业务异常语义),提供含库存信息的构造方法:
public class InsufficientStockException extends RuntimeException {
private final long required;
private final long available;
<pre class="brush:php;toolbar:false;">public InsufficientStockException(long required, long available) {
super(String.format("库存不足:需 %d,仅剩 %d", required, available));
this.required = required;
this.available = available;
}
// 可选:提供 getter,便于上层提取数据做日志或响应
public long getRequired() { return required; }
public long getAvailable() { return available; }}
在扣减逻辑中主动校验并抛出
不要依赖数据库唯一约束或更新行数为 0 来“事后发现”失败。应在业务层明确判断:
- 查出当前商品可用库存(注意加锁或版本控制,防并发超卖)
- 比较待扣减数量与可用库存
- 若
required > available,直接throw new InsufficientStockException(required, available)
示例片段:
public void deductStock(Long skuId, int quantity) {
Stock stock = stockMapper.selectBySkuId(skuId); // 假设已加 for update 或使用乐观锁
if (stock == null || stock.getAvailable() 确保异常被合理捕获和响应
抛出只是第一步,必须有对应的处理机制:
-
Controller 层统一捕获:用
@ExceptionHandler(InsufficientStockException.class)返回标准错误码(如 400)和提示消息 -
事务回滚:默认情况下,抛出
RuntimeException会触发 Spring 的事务回滚(需确认方法在事务代理内执行) - 日志记录:在异常处理器中记录关键参数(skuId、quantity、available),方便排查
避免常见误区
- 不要把库存校验和扣减拆成两个独立的数据库操作(先查再更新),中间可能被其他请求修改,应合并为原子操作(如 select for update + update)或使用乐观锁
- 不要用
Exception或IllegalArgumentException替代自定义异常——语义模糊,难以区分库存不足和其他参数错误 - 不要在 service 方法里吞掉这个异常或简单打印,导致上层无法感知失败
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











