苍穹外卖 - 菜品起售/停售复习笔记

1. 业务逻辑核心

这个功能不仅仅是"改个状态"那么简单,它包含了一个隐形的级联逻辑。

  • 起售 (Status = 1):

  • 逻辑 :非常简单,只修改菜品表 (dish) 的状态即可。

  • 影响:不影响其他表。

  • 停售 (Status = 0):

  • 逻辑 :"连坐机制"。

  • 核心规则:如果一道菜(如"宫保鸡丁")不卖了,那么包含这道菜的所有套餐(如"超值双人餐")也必须立刻停止售卖。

  • 原因:防止用户点了套餐,结果厨房发现缺菜做不出来,导致客诉。


2. 接口设计与参数传递

  • 接口地址 :POST /admin/dish/status/{status}?id={id}
  • 参数解剖:
参数位置 形式 注解 含义
路径 (Path) /status/{status} @PathVariable 做什么操作? (1=起售, 0=停售)
查询 (Query) ?id=xxx Long id 操作哪个对象? (菜品ID)

3. 核心代码实现 (Code Implementation)

3.1 Service 层 (DishServiceImpl)

使用了 Builder模式 构建对象,并使用了 批量更新 优化了级联逻辑。

java 复制代码
    @Override
    @Transactional // 1. 事务控制:保证"菜品停售"和"套餐停售"原子性
    public void startOrStop(Integer status, Long id) {
        // 修改菜品状态
        Dish dish = Dish.builder()
                .id(id)
                .status(status)
                .build();
        dishMapper.update(dish);

        // 如果是停售操作,还需要将关联的套餐也停售
        if (status.equals(StatusConstant.DISABLE)) {
            // 查询关联的套餐id
            List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(Arrays.asList(id));
            
            // 2. 判空防止 NPE (NullPointerException)
            if (setmealIds != null && !setmealIds.isEmpty()) {
                // 3. 批量将关联的套餐全部停售 (性能优化点)
                setmealMapper.updateStatusBatch(setmealIds, StatusConstant.DISABLE);
            }
        }
    }

3.2 Mapper 层 (动态 SQL)

这里有两个关键的 XML 配置,分别对应单条更新 和批量更新。

(1) DishMapper.xml - 单条动态更新

必须使用 <if> 标签,防止将未传入的字段误更新为 null。

xml 复制代码
    <update id="update">
        update dish
        <set>
            <if test="name != null">name = #{name},</if>
            <if test="categoryId != null">category_id = #{categoryId},</if>
            <if test="price != null">price = #{price},</if>
            <if test="image != null">image = #{image},</if>
            <if test="description != null">description = #{description},</if>
            <if test="status != null">status = #{status},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateUser != null">update_user = #{updateUser},</if>
        </set>
        where id = #{id}
    </update>
(2) SetmealMapper.xml - 批量更新

使用 <foreach> 标签配合 IN 语句,实现一次交互更新多条数据。

xml 复制代码
    <update id="updateStatusBatch">
        update setmeal set status = #{status} where id in
        <foreach collection="setmealIds" item="setmealId" separator="," open="(" close=")">
            #{setmealId}
        </foreach>
    </update>

相关推荐
凤凰院凶涛QAQ1 天前
《Java版数据结构 & 集合类剖析》Map & Set & 反射:“从哈希碰撞到红黑树转换,反射帮你扒开 HashMap 的桶数组看个究竟”
java·数据结构·算法
H.莓飛1 天前
【数据结构】排序_OJ题(一):计数、桶与排序后的处理
java·开发语言·数据结构
wangchunyu1141 天前
JAVA AQS与Lock实现原理(含CAS)
java·开发语言·word
w_zero_one1 天前
算法--模拟
java·数据结构·算法
Javatutouhouduan1 天前
阿里1658页Java面试题总结(含答案)
java·高并发·java面试·java面试题·后端开发·java程序员·java八股文
秋天的怀念_David1 天前
算法一千零一夜 · 第十三夜 幻方,武侠世界里的数学迷宫
java·程序人生·算法
专业程序开发源1 天前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
秋天的怀念_David1 天前
算法一千零一夜 · 第十四夜 幻方与奇妙的二进制
java·程序人生·算法
thefool1122661 天前
网络编程^
java
Thinker QAQ1 天前
并发编程(十一):Shared Memory 与 Message Passing——关系与组合使用
java·python·go·并发编程·shared memory·message passing