6--苍穹外卖-SpringBoot项目中菜品管理 详解(二)

news2024/9/28 23:27:08

目录

菜品分页查询

需求分析和设计

代码开发

设计DTO类

设计VO类

Controller层

Service层接口

Service层实现类

Mapper层

功能测试

删除菜品

需求设计和分析

代码开发

Controller层

Service层接口

Service层实现类

Mapper层

功能测试

修改菜品

需求分析和设计

代码开发

根据id查询菜品实现

Controller层

Service层接口

Service层实现类

Mapper层

修改菜品实现

Controller层

Service层接口

Service层实现类

Mapper层

功能测试


  
1--苍穹外卖-SpringBoot项目介绍及环境搭建 详解-CSDN博客

2--苍穹外卖-SpringBoot项目中员工管理 详解(一)-CSDN博客

3--苍穹外卖-SpringBoot项目中员工管理 详解(二)-CSDN博客

4--苍穹外码-SpringBoot项目中分类管理 详解-CSDN博客

5--苍穹外卖-SpringBoot项目中菜品管理 详解(一)-CSDN博客

6--苍穹外卖-SpringBoot项目中菜品管理 详解(二)-CSDN博客

7--苍穹外卖-SpringBoot项目中套餐管理 详解(一)-CSDN博客

8--苍穹外卖-SpringBoot项目中套餐管理 详解(二)-CSDN博客

9--苍穹外卖-SpringBoot项目中Redis的介绍及其使用实例 详解-CSDN博客

菜品分页查询

需求分析和设计

业务规则:

  • 根据页码展示菜品信息

  • 每页展示10条数据

  • 分页查询时可以根据需要输入菜品名称、菜品分类、菜品状态进行查询

代码开发

设计DTO类

根据菜品分页查询接口定义设计对应的DTO:

在sky-pojo模块中

package com.sky.dto;

import lombok.Data;

import java.io.Serializable;

@Data
public class DishPageQueryDTO implements Serializable {

    private int page;

    private int pageSize;

    private String name;

    //分类id
    private Integer categoryId;

    //状态 0表示禁用 1表示启用
    private Integer status;

}
设计VO类

根据菜品分页查询接口定义设计对应的VO:(在返回的数据中categoryName属于另外一个文件中,需要使用VO转换属性为json,方便前端展示)

在sky-pojo模块中

package com.sky.vo;

import com.sky.entity.DishFlavor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DishVO implements Serializable {

    private Long id;
    //菜品名称
    private String name;
    //菜品分类id
    private Long categoryId;
    //菜品价格
    private BigDecimal price;
    //图片
    private String image;
    //描述信息
    private String description;
    //0 停售 1 起售
    private Integer status;
    //更新时间
    private LocalDateTime updateTime;
    //分类名称
    private String categoryName;
    //菜品关联的口味
    private List<DishFlavor> flavors = new ArrayList<>();

    //private Integer copies;
}
Controller层

根据接口定义创建DishController的page分页查询方法:

//菜品分页查询
    @GetMapping("/page")
    @ApiOperation("菜品分页查询")
    public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){
        log.info("菜品分页查询:{}",dishPageQueryDTO);
        PageResult pageResult=dishService.pageQuery(dishPageQueryDTO);
        return Result.success(pageResult);
    }
Service层接口

在 DishService 中扩展分页查询方法:

 //菜品分页查询
    PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);
Service层实现类

在 DishServiceImpl 中实现分页查询方法:

 //菜品分页查询
    @Override
    public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
       Page<DishVO> page= dishMapper.pageQuery(dishPageQueryDTO);
        return new PageResult(page.getTotal(),page.getResult());
    }
Mapper层

在 DishMapper 接口中声明 pageQuery 方法:

 //菜品分页查询
    Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);

在 DishMapper.xml 中编写SQL:

 <select id="pageQuery" resultType="com.sky.vo.DishVO">
        select d.* ,c.name as categoryName from dish d left outer join category c on d.category_id=c.id
        <where>
            <if test="name!=null">
                and d.name like concat('%',#{name},'%')
            </if>
        <if test="categoryId!=null">
            and d.category_id=#{categoryId}
        </if>
        <if test="status!=null">
            and d.status=#{status}
        </if>
        </where>
        order by d.create_time desc
    </select>

功能测试

删除菜品

需求设计和分析

业务规则:

  • 可以一次删除一个菜品,也可以批量删除菜品

  • 起售中的菜品不能删除

  • 被套餐关联的菜品不能删除

  • 删除菜品后,关联的口味数据也需要删除掉

代码开发

Controller层

根据删除菜品的接口定义在DishController中创建方法:

//菜品批量删除
    @DeleteMapping
    @ApiOperation("菜品批量删除")
    public Result<String> delete(@RequestParam List<Long> ids){
        //@RequestParam注解使用mvc框架,可以获取到参数1,2,3中的变量值
        log.info("菜品批量删除,{}",ids);
        dishService.deleteBatch(ids);
        return Result.success();
    }
Service层接口

在DishService接口中声明deleteBatch方法:

  //菜品批量删除
    void deleteBatch(List<Long> ids);
Service层实现类

在DishServiceImpl中实现deleteBatch方法:

  //菜品批量删除

    @Transactional//事务
    public void deleteBatch(List<Long> ids) {
        //判断当前菜品是否能够删除---是否存在起售中的菜品
        for (Long id : ids) {
            //根据主键查询菜品
            Dish dish=dishMapper.getById(id);
            //查询是否起售
            if (Objects.equals(dish.getStatus(), StatusConstant.ENABLE)){
                //当前菜品处于起售中,不能删除
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }

        //判断当前菜品是否能够删除---是否被套餐关联了
        List<Long> setmealIds=setmealDishMapper.getSetmealIdsByDishIds(ids);
        if (setmealIds!=null&& !setmealIds.isEmpty()){
            //当前菜品被套餐关联了,不能删除
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }

        //删除菜品表中的菜品数据
        for (Long id : ids) {
            dishMapper.deleteById(id);
            //删除菜品关联的口味数据
            dishFlavorMapper.deleteByDishId(id);
        }
Mapper层

在DishMapper中声明getById方法,并配置SQL:

 //根据主键查询菜品
    @Select("select *from dish where id=#{id}")
    Dish getById(Long id);

创建SetmealDishMapper,声明getSetmealIdsByDishIds方法,并在xml文件中编写SQL:

package com.sky.mapper;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface SetmealDishMapper {
    //根据菜品id查询对应的套餐id
    List<Long> getSetmealIdsByDishIds(List<Long> dishIds);


}

SetmealDishMapper.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.SetmealDishMapper">

    <select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
        select setmeal_id from setmeal_dish where dish_id in
        <foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
            #{dishId}
        </foreach>
    </select>
</mapper>

在DishMapper.java中声明deleteById方法并配置SQL:

    //根据主键删除菜品数据
    @Delete("delete from dish where id=#{id}")
    void deleteById(Long id);

在DishFlavorMapper中声明deleteByDishId方法并配置SQL:

 //根据菜品id删除对应的口味数据
    @Delete("delete from dish_flavor where dish_id=#{dishId}")
    void deleteByDishId(Long dishId);

 性能优化

在DishServiceImpl中,删除菜品是一条一条传送执行的,大大降低了执行效率,原代码如下:

//删除菜品表中的菜品数据
        for (Long id : ids) {
            dishMapper.deleteById(id);
            //删除菜品关联的口味数据
            dishFlavorMapper.deleteByDishId(id);
        }

为了提高性能,进行修改,使用动态sql执行删除操作

 //根据菜品id集合批量删除菜品数据
        //sql:delete from dish where id in(?,?,?)
        dishMapper.deleteByIds(ids);
        
        //根据菜品id集合批量删除关联的口味数据
        //sql:delete from dish_flavor where dish_id in(?,?,?)
        dishMapper.deleteByDishIds(ids);

在DishMapper中

 //根据菜品id集合批量删除菜品
    void deleteByIds(List<Long> ids);

    //根据菜品id集合批量删除关联的口味数据
    void deleteByDishIds(List<Long> dishId);

在DishMapper.xml中

 <delete id="deleteByIds">
        delete from dish where id in
                         <foreach collection="ids" open="(" separator="," close=")" item="id">
                             #{id}
                         </foreach>
    </delete>
    <delete id="deleteByDishIds">
        delete from dish_flavor where dish_id in
                                <foreach collection="dishIds" open="(" close=")" separator="," item="dishId">
                                    #{dishId}
                                </foreach>
    </delete>

功能测试

进行前后端联调,删除成功

修改菜品

需求分析和设计

接口:

  • 根据id查询菜品

  • 根据类型查询分类(已实现)

  • 文件上传(已实现)

  • 修改菜品

代码开发

根据id查询菜品实现

Controller层

根据id查询菜品的接口定义在DishController中创建方法:

 //根据id查询菜品
    @GetMapping("/{id}")
    @ApiOperation("根据id查询菜品")
    public  Result<DishVO> getById(@PathVariable Long id){
        log.info("根据id查询菜品:{}",id);
        DishVO dishVO=dishService.getByIdWithFlavor(id);
        return  Result.success(dishVO);
    }
Service层接口

在DishService接口中声明getByIdWithFlavor方法:

 //根据id查询菜品和对应的口味数据
    DishVO getByIdWithFlavor(Long id);
Service层实现类

在DishServiceImpl中实现getByIdWithFlavor方法:

//根据id查询菜品和对应的口味数据
    @Override
    public DishVO getByIdWithFlavor(Long id) {
        //根据id查询菜品数据
        Dish dish=dishMapper.getById(id);

        //根据菜品id查询口味数据
        List<DishFlavor> dishFlavors=dishFlavorMapper.getByDishId(id);

        //将查询到的数据封装到VO
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish,dishVO);
        dishVO.setFlavors(dishFlavors);

        return dishVO;
    }
Mapper层

在DishFlavorMapper中声明getByDishId方法,并配置SQL:

//根据id查询对应的口味数据
    @Select("select *from dish_flavor where dish_id=#{dishId}")
    List<DishFlavor> getByDishId(Long dishId);

修改菜品实现

Controller层

根据修改菜品的接口定义在DishController中创建方法:

 //修改菜品
    @PutMapping
    @ApiOperation("修改菜品")
    public Result<String> update(@RequestBody DishDTO dishDTO){
        log.info("修改菜品:{}",dishDTO);
        dishService.updateWithFlavor(dishDTO);
        return Result.success();
    }
Service层接口

在DishService接口中声明updateWithFlavor方法:

 //根据id修改菜品基本信息和对应的口味数据
    void updateWithFlavor(DishDTO dishDTO);
Service层实现类

在DishServiceImpl中实现updateWithFlavor方法:

//根据id修改菜品基本信息和对应的口味信息
    @Override
    public void updateWithFlavor(DishDTO dishDTO) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);


        //修改菜品表基本信息
        dishMapper.update(dish);

        //删除原有的口味数据
        dishFlavorMapper.deleteByDishId(dishDTO.getId());

        //重新插入口味数据
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors!=null&& !flavors.isEmpty()){
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(dishDTO.getId());
            });
            //向口味表插入n条数据
            dishFlavorMapper.insertBatch(flavors);
        }


    }
Mapper层

在DishMapper中,声明update方法:

 //根据id动态修改菜品数据
    @AutoFill(value = OperationType.UPDATE)
    void update(Dish dish);

并在DishMapper.xml文件中编写SQL:

 <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>

功能测试

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring--boot自动配置原理案例--阿里云--starter

Spring–boot自动配置原理案例–阿里云–starter 定义这个starter的作用是它可以将阿里云的工具类自动放入IOC容器中&#xff0c;供人使用。 我们看一看构建starter的过程&#xff0c;其实就是在atuoconfigure模块中加入工具类&#xff0c;然后写一个配置类在其中将工具类放入…

【ChromeDriver安装】爬虫必备

以下是安装和配置 chromedriver 的步骤&#xff1a; 1. 确认 Chrome 浏览器版本 打开 Chrome 浏览器&#xff0c;点击右上角的菜单按钮&#xff08;三个点&#xff09;&#xff0c;选择“帮助” > “关于 Google Chrome”。 2. 下载 Chromedriver 根据你的 Chrome 版本&…

【研赛A题成品论文】24华为杯数学建模研赛A题成品论文+可运行代码丨免费分享

2024华为杯研究生数学建模竞赛A题精品成品论文已出&#xff01; A题 风电场有功功率优化分配 一、问题分析 A题是一道工程建模与优化类问题&#xff0c;其目的是根据题目所给的附件数据资料分析风机主轴及塔架疲劳损伤程度&#xff0c;以及建立优化模型求解最优有功功率分配…

哪些AI软件能轻松搞定你的文案、总结、论文、计划书?

大家好&#xff01;在我们每天紧张忙碌的生活中&#xff0c;有时候一天结束时&#xff0c;我们还有一堆事情等着处理。 图片 但别担心&#xff0c;今天我要为大家介绍几款AI软件&#xff0c;它们可以在你忙碌的一天结束后&#xff0c;成为你的得力助手&#xff0c;帮你轻松管…

初识Tomcat

Tomcat是一款可以运行javaWebAPP的服务器软件。 一个服务器想要执行java代码&#xff0c;则需要JRE&#xff08;jvm、java运行环境等&#xff09;&#xff0c;但是需要执行javaWEB项目则还需要服务器软件&#xff0c;Tomacat就是其中很流行的一款。因为一个javaWEB项目会有很多…

Accelerate单卡,多卡config文件配置

依赖库 from accelerate import Accelerator from accelerate import DistributedDataParallelKwargs ddp_kwargs DistributedDataParallelKwargs(find_unused_parametersTrue) accelerator Accelerator(kwargs_handlers[ddp_kwargs]) 代码中删除所有的.cuda() 或者to(devic…

Xshell连接服务器

一、Xshell-7.0.0164p、Xftp 7下载 1.1、文件下载 通过网盘分享的文件&#xff1a;xshell 链接: https://pan.baidu.com/s/1qc0CPv4Hkl19hI9tyvYZkQ 提取码: 5snq –来自百度网盘超级会员v2的分享 1.2、ip连接 下shell和xftp操作一样&#xff1a;找到文件—》新建—》名称随…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,1-1

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…

论文不同写作风格下的ChatGPT提示词分享

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 在学术论文写作中&#xff0c;不同的写作风格能显著影响文章的表达效果与读者的理解。无论是描述性、分析性、论证性&#xff0c;还是批判性写作风格&#xff0c;合理选择和运用恰当的写…

生成模型小结

突然发现之前整理的makedown有必要放在博客里面,这样不同的设备之间可以直接观看达到复习的效果. GAN G和D不断的博弈提高自己。GAN的优点是保真度比较高&#xff0c;缺点是多样性比较低。 (auto-encoder)AE&#xff0c;DAE、VAE、VQVAE 输入x&#xff0c;经过编码器生成&…

Elasticsearch学习笔记(2)

索引库操作 在Elasticsearch中&#xff0c;Mapping是定义文档字段及其属性的重要机制。 Mapping映射属性 type&#xff1a;字段数据类型 1、字符串&#xff1a; text&#xff1a;可分词的文本&#xff0c;适用于需要全文检索的情况。keyword&#xff1a;用于存储精确值&am…

二阶低通滤波器(Simulink仿真)

1、如何将S域传递函数转为Z域传递函数 传递函数如何转化为差分方程_非差分方程转成差分方程-CSDN博客文章浏览阅读4.1k次,点赞4次,收藏50次。本文介绍了如何将传递函数转化为差分方程,主要适用于PLC和嵌入式系统。通过MATLAB的系统辨识工具箱获取传递函数,并探讨了离散化方…

OpenCV第十二章——人脸识别

1.人脸跟踪 1.1 级联分类器 OpenCV中的级联分类器是一种基于AdaBoost算法的多级分类器&#xff0c;主要用于在图像中检测目标对象。以下是对其简单而全面的解释&#xff1a; 一、基本概念 级联分类器&#xff1a;是一种由多个简单分类器&#xff08;弱分类器&#xff09;级联组…

Yolov10环境配置

参考文章&#xff1a;1.YOLOv10超详细环境搭建以及模型训练&#xff08;GPU版本&#xff09;-CSDN博客 2.Windows下安装pytorch教程(下载.whl的方式)_pytorch whl-CSDN博客 安装步骤和文件夹顺序一样 1.安装CUDA和cuDNN 1.1安装CUDA 1.1.1查看当前你的电脑显卡支持的最高CUD…

Docker从入门到精通_02 Docker魔法之旅:零基础Linux用户也能轻松驾驭的安装部署指南

文章目录 Docker从入门到精通_02 Docker魔法之旅&#xff1a;零基础Linux用户也能轻松驾驭的安装部署指南一 操作系统安装二 操作系统环境准备2.1 关闭防火墙2.1.2.2 关闭selinux2.2.1 临时关闭selinux2.2.2 永久关闭selinux 三 docker引擎安装3.1 从get.docker.com 下载 get-d…

02-ZYNQ linux开发环境安装,基于Petalinux2022.2和Vitis2022.2

petalinux安装 Petalinux 工具是 Xilinx 公司推出的嵌入式 Linux 开发套件&#xff0c;包括了 u-boot、Linux Kernel、device-tree、rootfs 等源码和库&#xff0c;以及 Yocto recipes&#xff0c;可以让客户很方便的生成、配置、编译及自定义 Linux 系统。Petalinux 支持 Ver…

了解 如何使用同快充充电器给不同设备快速充电

在这科技发展迅速的时代&#xff0c;快充技术已经走进了我们生活&#xff0c;不得不说有了快充技术的对比&#xff0c;传统的充电模式已经满足不了人们对充电速度的要求。就比如用华为输出100 W快充充电器为手机充电大概需要23分钟充满100%电量&#xff0c;而传统的充电器则需要…

可以免费制作表情包的AI工具来了!

一直想自己制作一套表情包&#xff0c;但一直没有找到好用的工具&#xff0c;要么就是太麻烦&#xff0c;要么就是不免费。 今天AI表情包免费制作工具来了&#xff0c;手机就可以直接做表情包&#xff0c;非常方便。 先看效果~ 工具用到的是通义APP&#xff0c;可以在频道中找…

车辆重识别(利用扩散模型合成有效数据进行行人再识别预训练)论文阅读2024/9/27

[1]Synthesizing Efficient Data with Diffusion Models for Person Re-Identification Pre-Training 作者&#xff1a;Ke Niu1, Haiyang Yu1, Xuelin Qian2, Teng Fu1, Bin Li1, Xiangyang Xue1*单位&#xff1a;1复旦大学, 2西北工业大学 摘要&#xff1a; 现有的行人重识别…

若伊(前后端分离)学习笔记

基础应用篇 1. 若伊搭建 若伊版本 若依官方针对不同开发需求提供了多个版本的框架&#xff0c;每个版本都有其独特的特点和适用场景&#xff1a; 前后端混合版本 &#xff1a;RuoYi结合了SpringBoot和Bootstrap的前端开发框架&#xff0c;适合快速构建传统的Web应用程序&…