订单逻辑删除要同时处理主表明细

zjc 于 2026-08-20 发布

表配置了逻辑删除后,删除并不是真正的 DELETE,而是把标记字段更新为已删除。主表和明细如果分开处理,很容易留下一边可见、一边不可见的数据。

一、服务层统一删除

@Transactional(rollbackFor = Exception.class)
public boolean removeWithDetails(Long orderId) {
    if (!removeById(orderId)) {
        return false;
    }
    orderDetailService.remove(new LambdaQueryWrapper<OrderDetail>()
            .eq(OrderDetail::getOrderId, orderId));
    return true;
}

https://github.com/springvortex/spring-cloud-alibaba/blob/main/service-provider/src/main/java/com/zjc/provider/service/impl/OrderServiceImpl.java

Controller 只传订单 ID,不关心主明细结构。

二、返回 false 和抛异常是两种语义

订单不存在时返回 false,由接口转换成“资源不存在”;数据库操作失败时抛异常,由事务回滚并进入全局错误处理。二者不要混成同一种处理方式。

三、逻辑删除同样要事务

主表标记删除成功后,如果明细更新失败,事务回滚,两边恢复一致。没有事务时,接口可能返回成功,但数据状态已经裂开。

四、查询也要遵守同一假设

订单列表查询不带明细,单个订单查询聚合明细。后续如果做统计报表,必须记得逻辑删除字段,否则会把历史删除数据重新算进去。

五、经验总结

逻辑删除解决的是审计和恢复需求,不是让删除变得不用考虑一致性。主从结构一旦出现,删除永远是一个业务事务。