苍穹外卖04 (新增内表的外键id获取,多表分页查询,多表批量删除,修改先查在改内表外键id用主表的,起售时包含了“停售”状态的外关联表)

1. 新增套餐

1 需求分析和设计

业务规则:

  • 套餐名称唯一

  • 套餐必须属于某个分类

  • 套餐必须包含菜品

  • 名称、分类、价格、图片为必填项

  • 添加菜品窗口需要根据分类类型来展示菜品

  • 新增的套餐默认为停售状态

2 代码实现

1 根据分类id查询菜品

DishController

@GetMapping("/list")
@ApiOperation("根据分类id查询菜品列表")
public Result queryDishesByCategoryId(Long categoryId){
    return dishService.queryDishesByCategoryId(categoryId);
}


----------------
DishService

/**
 * 根据分类id查询菜品列表
 * @param categoryId 分类id
 * @return categoryId对应的菜品列表
 */
Result queryDishesByCategoryId(Long categoryId);

----------------
DishServiceImpl

@Override
public Result queryDishesByCategoryId(Long categoryId) {
    List<Dish> dishes = dishMapper.selectByCategoryId(categoryId);
    return Result.success(dishes);
}

----------------
DishMapper

@Select("select * from dish where category_id = #{categoryId}")
List<Dish> selectByCategoryId(Long categoryId);




2 新增套餐

SetmealController

package com.sky.controller.admin;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Api(tags = "套餐管理相关接口")
@RequestMapping("/admin/setmeal")
public class SetmealController {
    @Autowired
    private SetmealService setmealService;

    @PostMapping
    @ApiOperation("新增套餐")
    public Result addSetmeal(@RequestBody SetmealDTO dto){
        return setmealService.addSetmeal(dto);
    }
}


-----------------
SetmealService

package com.sky.service;
import com.sky.dto.SetmealDTO;
import com.sky.result.Result;
import java.util.List;

public interface SetmealService {
    Result addSetmeal(SetmealDTO dto);

}

-----------------
SetmealServiceImpl

package com.sky.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.SetmeatlDishMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
@Service
public class SetmealServiceImpl implements SetmealService {
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmeatlDishMapper setmealDishMapper;

    @Override
    @Transactional
    public Result addSetmeal(SetmealDTO dto) {
        //1. 保存套餐
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(dto, setmeal);
        setmealMapper.insert(setmeal);
        //2. 保存套餐里关联的菜品
        List<SetmealDish> setmealDishes = dto.getSetmealDishes();
        if (setmealDishes != null && setmealDishes.size() > 0) {
            setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmeal.getId()));
            setmealDishMapper.batchInsert(setmealDishes);
        }
        return Result.success();
    }
}


-----------------
SetmealMapper

/**
     * 新增套餐
     * @param setmeal
     */
@AutoFill(OperationType.INSERT)
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into setmeal(category_id, name, price, status, description, image, create_time, update_time, create_user, update_user) " +
        "        values (#{categoryId},#{name},#{price},#{status},#{description},#{image},#{createTime},#{updateTime},#{createUser},#{updateUser})")
void insert(Setmeal setmeal);

-------------------
SetmeatlDishMapper

void batchInsert(List<SetmealDish> setmealDishes);

----------------
SetmeatlDishMapper.xml

<insert id="batchInsert">
    insert into setmeal_dish (setmeal_id, dish_id, name, price, copies) values
    <foreach collection="setmealDishes" item="sd" separator=",">
        (#{sd.setmealId}, #{sd.dishId}, #{sd.name}, #{sd.price}, #{sd.copies})
    </foreach>
</insert>

2. 套餐分页查询

1 需求分析和设计

业务规则:

  • 根据页码进行分页展示

  • 每页展示10条数据

  • 可以根据需要,按照套餐名称、分类、售卖状态进行查询

2 代码实现

SetmealController

@GetMapping("/page")
@ApiOperation("分页查询套餐")
public Result querySetmealsByPage(SetmealPageQueryDTO dto){
    return setmealService.querySetmealsByPage(dto);
}

----------------
SetmealService

/**
     * 分页查询套餐
     * @param dto
     * @return
     */
Result querySetmealsByPage(SetmealPageQueryDTO dto);

----------------
SetmealServiceImpl

@Override
public Result querySetmealsByPage(SetmealPageQueryDTO dto) {
    //1. 开启分页
    PageHelper.startPage(dto.getPage(), dto.getPageSize());
    //2. 查询列表
    Page<SetmealVO> page = setmealMapper.selectByPage(dto);
    //3. 封装结果
    PageResult pageResult = new PageResult(page.getTotal(), page.getResult());
    return Result.success(pageResult);
}

--------------
SetmealMapper

/**
     * 分页查询套餐列表
     * @param dto
     * @return
     */
Page<SetmealVO> selectByPage(SetmealPageQueryDTO dto);

--------------
SetmealMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sky.mapper.SetmealMapper">
    <select id="selectByPage" resultType="com.sky.vo.SetmealVO">
        select s.*, c.name categoryName from setmeal s left join category c on s.category_id = c.id
        <where>
            <if test="name!=null and name.length()>0">
                and s.name like concat('%', #{name}, '%')
            </if>
            <if test="categoryId!=null">
                and s.category_id = #{categoryId}
            </if>
            <if test="status!=null">
                and s.status = #{status}
            </if>
        </where>
        order by s.create_time desc
    </select>
</mapper>


3. 删除套餐

1 需求分析和设计

业务规则:

  • 可以一次删除一个套餐,也可以批量删除套餐

  • 起售中的套餐不能删除

2 代码实现

SetmealController

@DeleteMapping
@ApiOperation("删除套餐")
public Result batchDeleteSetmealsByIds(@RequestParam List<Long> ids){
    return setmealService.batchDeleteSetmealsByIds(ids);
}

----------
SetmealService

/**
     * 批量删除套餐
     * @param ids
*/
Result batchDeleteSetmealsByIds(List<Long> ids);

----------
SetmealServiceImpl

@Override
@Transactional
public Result batchDeleteSetmealsByIds(List<Long> ids) {
    //1. 如果有某个套餐是“起售”状态,则不允许删除
    int count = setmealMapper.selectEnableSetmealsCount(ids);
    if (count > 0) {
        throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
    }
    //2. 删除套餐
    setmealMapper.batchDeleteByIds(ids);
    //3. 删除套餐关联的菜品
    setmealDishMapper.batchDeleteBySetmealIds(ids);
    return Result.success();
}

-----------
SetmealMapper

/**
     * 查询 ids对应的套餐中,起售状态的套餐 数量
     * @param ids
     * @return
     */
int selectEnableSetmealsCount(List<Long> ids);

/**
     * 根据ids批量删除套餐
     * @param ids
     */
void batchDeleteByIds(List<Long> ids);

------------
SetmealMapper.xml

<select id="selectEnableSetmealsCount" resultType="int">
    select count(*) from setmeal where status = 1 and
    <foreach collection="ids" item="id" separator="," open="id in(" close=")">
        #{id}
    </foreach>
</select>

<delete id="batchDeleteByIds">
    delete from setmeal where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

---------------
SetmeatlDishMapper

    /**
     * 根据套餐ids,批量删除这些套餐包含的菜品关联关系
     * @param ids
     */
void batchDeleteBySetmealIds(List<Long> ids);

-----------
SetmeatlDishMapper.xml

<delete id="batchDeleteBySetmealIds">
    delete from setmeal_dish where setmeal_id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

4. 修改套餐

1 需求分析和设计

接口设计(共涉及到5个接口):

  • 根据id查询套餐

  • 根据类型查询分类(已完成)

  • 根据分类id查询菜品(已完成)

  • 图片上传(已完成)

  • 修改套餐

2 代码实现

1 根据id查询套餐

SetmealController

@GetMapping("/{id}")
@ApiOperation("根据id查询套餐")
public Result querySetmealById(@PathVariable("id") Long id) {
    return setmealService.querySetmealById(id);
}


----------
SetmealService

/**
 * 根据id查询套餐
 * @param id
 * @return
 */
Result querySetmealById(Long id);

-----------
SetmealServiceImpl

@Override
public Result querySetmealById(Long id) {
    //查询套餐信息
    Setmeal setmeal = setmealMapper.selectById(id);
    //查询套餐关联的菜品列表
    List<SetmealDish> setmealDishes = setmealDishMapper.selectBySetmealId(id);
    //封装成VO对象
    SetmealVO vo = new SetmealVO();
    BeanUtils.copyProperties(setmeal, vo);
    vo.setSetmealDishes(setmealDishes);
    return Result.success(vo);
}

----------
SetmealMapper

/**
 * 根据id查询套餐
 * @param id
 * @return
 */
@Select("select * from setmeal where id = #{id}")
Setmeal selectById(Long id);

----------
SetmeatlDishMapper

/**
 * 根据套餐id,查询套餐内包含的菜品
 * @param setmealId
 * @return
 */
@Select("select * from setmeal_dish where setmeal_id = #{setmealId}")
List<SetmealDish> selectBySetmealId(Long setmealId);

2 修改套餐

SetmealController

@PutMapping
@ApiOperation("修改套餐")
public Result updateSetmeal(@RequestBody SetmealDTO dto){
    return setmealService.updateSetmeal(dto);
}


----------
SetmealService

/**
 * 修改套餐
 * @param dto
 * @return
 */
Result updateSetmeal(SetmealDTO dto);

----------
SetmealServiceImpl

@Override
@Transactional
public Result updateSetmeal(SetmealDTO dto) {
    //1. 修改套餐
    Setmeal setmeal = new Setmeal();
    BeanUtils.copyProperties(dto, setmeal);
    setmealMapper.updateById(setmeal);
    //2. 修改套餐关联的菜品
    //2.1 删除套餐 之前关联的菜品
    setmealDishMapper.batchDeleteBySetmealIds(Collections.singletonList(dto.getId()));
    //2.2 重新添加 关联的菜品
    List<SetmealDish> setmealDishes = dto.getSetmealDishes();
    if (setmealDishes != null && setmealDishes.size() > 0) {
        setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmeal.getId()));
        setmealDishMapper.batchInsert(setmealDishes);
    }
    return Result.success();
}

-----------
SetmealMapper

/**
 * 根据id修改套餐
 * @param setmeal
 */
@AutoFill(OperationType.UPDATE)
void updateById(Setmeal setmeal);

-----------
SetmealMapper.xml

<update id="updateById">
    UPDATE setmeal
    <set>
        <if test="categoryId!=null">category_id = #{categoryId},</if>
        <if test="name!=null and name.length()>0">name = #{name},</if>
        <if test="price!=null">price = #{price},</if>
        <if test="status!=null">status = #{status},</if>
        <if test="description!=null and description.length()>0">description = #{description},</if>
        <if test="image!=null and image.length()>0">image = #{image},</if>
        <if test="updateTime!=null">update_time = #{updateTime},</if>
        <if test="updateUser!=null">update_user = #{updateUser}</if>
    </set>
    WHERE id = #{id}
</update>

5. 起售停售套餐

1 需求分析和设计

业务规则:

  • 可以对状态为起售的套餐进行停售操作,可以对状态为停售的套餐进行起售操作

  • 起售的套餐可以展示在用户端,停售的套餐不能展示在用户端

  • 起售套餐时,如果套餐内包含停售的菜品,则不能起售

2 代码实现

SetmealController

@PostMapping("/status/{status}")
@ApiOperation("启用禁用套餐")
public Result updateStatus(@PathVariable("status") Integer status, Long id){
    return setmealService.updateStatus(id, status);
}


--------------
SetmealService

/**
     * 套餐起售、停售
     * @param status
     * @param id
*/
Result updateStatus(Long id, Integer status);


-------------
SetmealServiceImpl

@Autowired
private DishMapper dishMapper;

@Override
public Result updateStatus(Long id, Integer status) {
    //起售套餐时,如果包含了“停售”状态的菜品,则不允许起售
    if (StatusConstant.ENABLE.equals(status)) {
        //查询套餐关联的所有菜品
        List<Dish> dishes = dishMapper.selectBySetmealId(id);
        //如果有任意一个菜品是“停售”状态,就抛出异常
        long count = dishes.stream()
            .filter(dish -> dish.getStatus().equals(StatusConstant.DISABLE))
            .count();
        if (count > 0) {
            throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
        }
    }

    //起售/停售套餐
    Setmeal setmeal = Setmeal.builder()
        .id(id)
        .status(status)
        .build();
    setmealMapper.updateById(setmeal);
    return Result.success();
}


-----------
DishMapper

/**
     * 根据套餐id查询菜品
     * @param setmealId
     * @return
*/
@Select("select * from dish where id in(select dish_id from setmeal_dish where setmeal_id = #{setmealId})")
List<Dish> selectBySetmealId(Long setmealId);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/506072.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

手机有线投屏到直播姬pc端教程

1 打开哔哩哔哩直播姬客户端并登录(按下图进行操作) 2 手机用usb数据线连接电脑(若跳出安装驱动的弹窗点击确定或允许),usb的连接方式为仅充电(手机差异要求为仅充电),不同品牌手机要求可能不一样,根据实际的来 3 在投屏过程中不要更改usb的连接方式(不然电脑会死机需要重启) …

SAP 学习笔记 - 系统移行业务 - Migration cockpit工具 - 移行Material(品目)

本章开始&#xff0c;来研究研究移行工具 Migration cockpit。 理论啥的先放一边&#xff0c;来先做一个简单的实例&#xff0c;以对 Migration cockpit 有个大概的印象。 这里就先做一个移行品目的例子。 1&#xff0c;LTMC 启动Migration cockpit工具 默认给我启动了 IE &a…

C++11入门手册第二节,学完直接上手Qt(共两节)

C++多线程 #include <thread>:C++多线程库 #include <mutex>:C++互斥量库 #include <future>:C++异步库 多线程介绍 线程的创建 void entry_1() { }以普通函数作为线程入口函数:void entry_2(int val) { }​std::thread my_thread_1(entry_1);std::thr…

【b站李炎恢】Vue.js Element UI 下 | 十天技能课堂 | 更新中... | 李炎恢

课程地址&#xff1a;【Vue.js Element UI | 十天技能课堂 | 更新中... | 李炎恢】 https://www.bilibili.com/video/BV1U54y127GB/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 备注&#xff1a;虽然标题声明还在更新中&#xff0c;但是看一些常用…

npm软件包管理器

npm软件包管理器 一.npm 使用步骤二.npm安装所有依赖三.npm全局软件包-nodemon pm 简介链接&#xff1a; 软件包管理器&#xff0c;用于下载和管理 Node.js 环境中的软件包 一.npm 使用步骤 1.初始化清单文件&#xff1a; npm init -y &#xff08;得到 package.json 文件&am…

Django DRF视图

文章目录 一、DRF类视图介绍APIViewGenericAPIView类ViewSet类ModelViewSet类重写方法 二、Request与ResponseRequestResponse 参考 一、DRF类视图介绍 在DRF框架中提供了众多的通用视图基类与扩展类&#xff0c;以简化视图的编写。 • View&#xff1a;Django默认的视图基类&…

RocketMQ(版本4.9.4)+RocketMQ_Dashbord环境搭建(生产者、消费者的前置环境搭建)

一、官方网站下载 RocketMQ源码包 https://rocketmq.apache.org/zh/docs/4.x/introduction/02quickstart 二、把rocketMQ上传到Linux环境下解压&#xff0c;编译&#xff0c;执行以下命令&#xff08;需要提前装jdk和maven并配置好环境变量&#xff09; unzip rocketmq-all-4…

计算机网络-从输入网址到访问网站的全过程

当我们在浏览器中输入一个网址并按下回车键时&#xff0c;会发生一系列复杂的过程&#xff0c;最终使我们能够看到网页的内容。以下是这个过程的详细步骤&#xff1a; 客户端&#xff1a;首先&#xff0c;用户在浏览器中键入网址&#xff0c;然后浏览器会根据这个网址生成一个H…

基于PHP的新闻管理系统(用户发布版)

有需要请加文章底部Q哦 可远程调试 基于PHP的新闻管理系统(用户发布版) 一 介绍 此新闻管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。本新闻管理系统采用用户发布新闻&#xff0c;管理员审核后展示模式。 技术栈&am…

区间预测 | Matlab实现带有置信区间的GRNN广义回归神经网络时间序列未来趋势预测

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 Matlab实现带有置信区间的GRNN广义回归神经网络时间序列未来趋势预测 带有置信区间的GRNN(广义回归神经网络)时间序列未来趋势预测结合了广义回归神经网络(GRNN)的预测能力和置信区间的统计度量,以提供对未来…

C刊级 | Matlab实现DBO-BiTCN-BiGRU-Attention蜣螂算法优化双向时间卷积双向门控循环单元融合注意力机制多变量回归预测

C刊级 | Matlab实现DBO-BiTCN-BiGRU-Attention蜣螂算法优化双向时间卷积双向门控循环单元融合注意力机制多变量回归预测 目录 C刊级 | Matlab实现DBO-BiTCN-BiGRU-Attention蜣螂算法优化双向时间卷积双向门控循环单元融合注意力机制多变量回归预测效果一览基本介绍模型描述程序…

DevSecOps安全工具链介绍

目录 一、概述 二、安全工具链在平台中的定位 2.1 概述 2.2 分层定位 2.2.1 不同阶段的安全工具 2.2.2 安全工具金字塔 2.3 安全流水线集成概览 2.3.1 概述 2.3.2 标准流水线集成安全工具链概览图 三、安全工具链分类 3.1 概述 3.2 威胁建模类 3.2.1 威胁建模的概念…

SQL | SQL 3小时快速入门学习笔记

【【数据库】SQL 3小时快速入门 #数据库教程 #SQL教程 #MySQL教程 #database#Python连接数据库】 课程链接 一、SQL 1.资料库管理系统&#xff08;Database Management System&#xff0c;简称DBMS&#xff09; 是整理资料的软件。其主要功能包括数据的存储、检索、更新和删除…

Matlab中的脚本和函数

Matlab中的脚本和函数 文章目录 Matlab中的脚本和函数脚本创建脚本代码注释函数创建函数局部函数嵌套函数私有函数匿名函数补充知识函数句柄测试环境:Win11 + Matlab R2021a 脚本 ​ Matlab脚本是最简单的程序文件类型。它们可用于自动执行一系列 Matlab 命令,如命令行重复执…

【opencv】教程代码 —features2D(5)旋转相机的基本全景拼接

基本全景拼接 panorama_stitching_rotating_camera.cpp 将第二张图像进行透视变换后与第一张图像拼接 #include <iostream> // 包含了一些用于输入输出的函数 #include <opencv2/core.hpp> // 包含了OpenCV核心库的一些常用类和函数 #include <opencv2/imgpro…

深度学习理论基础(二)神经网络基础篇

目录 一、基础知识点Ⅰ 参数部分Ⅱ 模型部分 二、普通神经网络模型搭建1. 准备数据集2. 划分数据集3. 搭建模型4. 训练网络5. 测试网络6. 保存与导入模型 神经网络通过学习大量样本的输入与输出特征之间的关系&#xff0c;以拟合出输入与输出之间的方程&#xff0c;学习完成后&…

Monkey 和 TextMonkey ---- 论文阅读

文章目录 Monkey贡献方法增强输入分辨率多级描述生成多任务训练 实验局限结论 TextMonkey贡献方法移位窗口注意&#xff08;Shifted Window Attention&#xff09;图像重采样器&#xff08;Image Resampler&#xff09;Token Resampler位置相关任务&#xff08;Position-Relate…

Collection与数据结构链表与LinkedList(三):链表精选OJ例题(下)

1. 分割链表 OJ链接 class Solution {public ListNode partition(ListNode head, int x) {if(head null){return null;//空链表的情况}ListNode cur head;ListNode formerhead null;ListNode formerend null;ListNode latterhead null;ListNode latterend null;//定义…

【AXIS】AXI-Stream FIFO设计实现(四)——异步时钟

前文介绍了几种同步时钟情况下的AXI Stream FIFO实现方式&#xff0c;一般来说&#xff0c;FIFO也需要承担异步时钟域模块间数据传输的功能&#xff0c;本文介绍异步AXIS FIFO的实现方式。 如前文所说&#xff0c;AXI-Stream FIFO十分类似于FWFT异步FIFO&#xff0c;推荐参考前…

书生浦语笔记一

2023年6月&#xff0c;InternLM的第一代大模型正式发布。仅一个月后&#xff0c;该模型以及其全套工具链被开源。随后&#xff0c;在8月份&#xff0c;多模态语料库chat7B和lagent也被开源。而在接下来的9月份&#xff0c;InternLM20B的开源发布进一步加强了全线工具链的更新。…