瑞吉外卖 - 删除分类功能(13)

news2024/11/28 0:45:13

某马瑞吉外卖单体架构项目完整开发文档,基于 Spring Boot 2.7.11 + JDK 11。预计 5 月 20 日前更新完成,有需要的胖友记得一键三连,关注主页 “瑞吉外卖” 专栏获取最新文章。
相关资料:https://pan.baidu.com/s/1rO1Vytcp67mcw-PDe_7uIg?pwd=x548
提取码:x548

文章目录

    • 1.需求分析
    • 2.代码开发
      • 2.1 执行过程分析
      • 2.2 代码实现
        • 2.2.1 准备实体类
        • 2.2.2 准备 Mapper 接口
        • 2.2.3 准备 Service 接口及实现类
        • 2.2.4 自定义 remove 方法
    • 3.功能测试

1.需求分析

在分类管理页面,可以对某个分类进行删除操作。但是需要注意的是,当分类关联了菜品或者套餐时,此分类不允许删除。

2.代码开发

2.1 执行过程分析

在开发代码之前,需要梳理一下整个程序的执行过程:

  1. 页面发送 ajax 请求,将参数(id)提交到服务端;
  2. 服务端 Controller 接收页面提交的数据并调用 Service 删除数据;
  3. Service 调用 Mapper 操作数据库。

下面同样简单看一下对应客户端发送的请求信息:

2.2 代码实现

注意,因为当分类关联了菜品或者套餐时,此分类不允许删除。因此,我们不能简单的调用 MyBatis Plus 提供的 categoryService.removeById(id) 方法直接进行删除。而是需要检查删除的分类是否关联了菜品或者套餐,因此我们需要进行一些功能上的扩展。

要完善分类删除功能,需要先准备基础的类和接口。首先需要实体类 DishSetmeal,菜品和套餐这两个实体类在前面同意导入实体的时候已经导入了,直接使用即可。

2.2.1 准备实体类

entity/Dish.java 实体类完整代码如下:

package cn.javgo.reggie_take_out.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 菜品
 */
@Data
public class Dish implements Serializable {
    // 用于序列化的版本号
    private static final long serialVersionUID = 1L;

    // 主键
    private Long id;

    //菜品名称
    private String name;

    //菜品分类id
    private Long categoryId;

    //菜品价格
    private BigDecimal price;

    //商品码
    private String code;

    //图片
    private String image;

    //描述信息
    private String description;

    //0 停售 1 起售
    private Integer status;

    //顺序
    private Integer sort;

    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

    @TableField(fill = FieldFill.INSERT)
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;

    //是否删除
    private Integer isDeleted;
}

entity/Setmeal.java 实体类完整代码如下:

package cn.javgo.reggie_take_out.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 套餐
 */
@Data
public class Setmeal implements Serializable {
    // 用于序列化的版本号
    private static final long serialVersionUID = 1L;

    // 主键
    private Long id;

    //分类id
    private Long categoryId;

    //套餐名称
    private String name;

    //套餐价格
    private BigDecimal price;

    //状态 0:停用 1:启用
    private Integer status;

    //编码
    private String code;

    //描述信息
    private String description;

    //图片
    private String image;

    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

    @TableField(fill = FieldFill.INSERT)
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;

    //是否删除
    private Integer isDeleted;
}

2.2.2 准备 Mapper 接口

对应的 mapper/DishMapper.java 接口如下:

package cn.javgo.reggie_take_out.mapper;

import cn.javgo.reggie_take_out.entity.Dish;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DishMapper extends BaseMapper<Dish> {
    
}

对应的 mapper/SetmealMapper.java 接口如下:

package cn.javgo.reggie_take_out.mapper;

import cn.javgo.reggie_take_out.entity.Setmeal;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
    
}

2.2.3 准备 Service 接口及实现类

对应的 service/DishService.java 接口如下:

package cn.javgo.reggie_take_out.service;

import cn.javgo.reggie_take_out.entity.Dish;
import com.baomidou.mybatisplus.extension.service.IService;

public interface DishService extends IService<Dish> {
    
}

对应的 service/impl/DishServiceImpl.java 实现类如下:

package cn.javgo.reggie_take_out.service.impl;

import cn.javgo.reggie_take_out.entity.Dish;
import cn.javgo.reggie_take_out.mapper.DishMapper;
import cn.javgo.reggie_take_out.service.DishService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
    
}

对应的 service/SetmealService.java 接口如下:

package cn.javgo.reggie_take_out.service;

import cn.javgo.reggie_take_out.entity.Setmeal;
import com.baomidou.mybatisplus.extension.service.IService;

public interface SetmealService extends IService<Setmeal> {

}

对应的 service/impl/SetmealServiceImpl.java 实现类如下:

package cn.javgo.reggie_take_out.service.impl;

import cn.javgo.reggie_take_out.entity.Setmeal;
import cn.javgo.reggie_take_out.mapper.SetmealMapper;
import cn.javgo.reggie_take_out.service.SetmealService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
    
}

2.2.4 自定义 remove 方法

想要实现我们的检查逻辑,就不能使用 MyBatis Plus 提供的现成方法了,我们需要在 CategoryService 接口中进行自定义:

public interface CategoryService extends IService<Category> {
    /**
     * 删除分类
     * @param id 分类id
     */
    public void remove(Long id);
}

然后在该接口的 CategoryServiceImpl 实现中进行抽象方法的实现:

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    @Resource
    private DishService dishService;

    @Resource
    private SetmealService setmealService;

    /**
     * 根据分类id删除分类,在删除之前判断是否关联了菜品和套餐,如果关联了则不能删除
     * @param id 分类id
     */
    @Override
    public void remove(Long id) {
        // 1.构造查询条件
        QueryWrapper<Dish> queryWrapper = new QueryWrapper<>();
        // 2.设置查询条件(根据分类id查询)
        queryWrapper.eq("category_id",id);
        // 3.查询到的菜品数量
        int count = dishService.count(queryWrapper);
        // 4.检查菜品数量,如果大于0则不能删除,抛出业务异常
        if (count > 0) {
            throw new CustomException("该分类下有菜品,不能删除");
        }

        // 5.构造查询条件
        QueryWrapper<Setmeal> queryWrapper2 = new QueryWrapper<>();
        // 6.设置查询条件(根据分类id查询)
        queryWrapper2.eq("category_id",id);
        // 7.查询到的套餐数量
        int count2 = setmealService.count(queryWrapper2);
        // 8.检查套餐数量,如果大于0则不能删除,抛出业务异常
        if (count2 > 0) {
            throw new CustomException("该分类下有套餐,不能删除");
        }

        // 9.删除分类
        baseMapper.deleteById(id);
    }
}

上述代码中涉及到的 common/CustomException.java 自定义业务异常如下:

package cn.javgo.reggie_take_out.common;

/**
 * 自定义业务异常
 */
public class CustomException extends RuntimeException {
    public CustomException(String message) {
        super(message);
    }
}

同时还需要在我们的 handler/GlobalExceptionHandler.java 全局异常处理器中进行该自定义异常的处理:

@ControllerAdvice(annotations = {RestController.class, Conditional.class})
@ResponseBody
public class GlobalExceptionHandler {

    /**
     * 处理自定义异常 CustomException
     * @param ex 异常对象
     * @return  响应对象
     */
    @ExceptionHandler(CustomException.class)
    public R<String> exceptionHandler(CustomException ex){
        return R.error(ex.getMessage());
    }
    
    // 省略其他方法
}

最后在 CategoryController 中编写对应的处理方法即可:

@RestController
@RequestMapping("/category")
public class CategoryController {
    @Resource
    private CategoryService categoryService;
    
    /**
     * 删除分类
     * @param id 分类id
     * @return R
     */
    @DeleteMapping
    public R<String> delete(Long id){
        categoryService.remove(id);
        return R.success("删除分类成功");
    }
    
    // 省略其他方法
}

3.功能测试

随便删除一个带有关联的分类进行删除操作:

新建一个没有关联的菜品分类:

删除新增的测试菜品,删除成功:

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

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

相关文章

chatgpt赋能Python-minhash_python

MinHash Python算法&#xff1a;优化大数据处理和搜索引擎 在如今互联网化和其他技术转型的时代&#xff0c;SEO已经成为许多企业和个人的必要条件。SEO方法(搜索引擎优化)一直在不断的发展&#xff0c;MinHash算法是其中之一。本篇文章将会介绍MinHash算法和它在Python中的实…

万金油表示真干不过,部门新来的00后测试员已把我卷崩溃,想离职了...

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&#x…

chatgpt赋能Python-numpy_分割

Numpy 分割&#xff1a;简介与应用 什么是 Numpy 分割&#xff1f; Numpy 是一种基于 Python 的科学计算库&#xff0c;它提供了对多维数组的支持。其中&#xff0c;分割是 Numpy 中一个非常重要的操作&#xff0c;它允许我们将一个数组沿着指定的轴切分成多个子数组&#xf…

synchronized 底层原理

synchronized 关键字的底层原理 jdk5 之前 synchronized 是重量级锁&#xff0c;但是jdk6 之后会有一个锁升级的过程 Monitor实现的锁属于重量级锁&#xff0c;你了解过锁升级吗? Java中的synchronized有偏向锁、轻量级锁、重量级锁三种形式&#xff0c;分别对应了锁只被一个…

Apache Zeppelin系列教程第六篇——Zengine调用Interpreter原理分析

Apache Zeppelin系列教程第五篇——Interpreter原理分析_诸葛子房_的博客-CSDN博客 Apache Zeppelin系列教程第四篇——JDBCInterpreter原理分析_诸葛子房_的博客-CSDN博客 前文介绍jdbc interpreter和interpreter模块交互代码&#xff0c;本篇文章主要分析Zengine调用Interp…

智能的本质人工智能与机器人领域的64个大问题阅读笔记(三)

目录 机器智能提高到人类的水平或者人类智能下降到机器的水平&#xff0c;都可以到达图灵点。 或许图灵测试是一个自我实现的预言&#xff1a;我们&#xff08;声称&#xff09;在打造“聪明”机器的同时&#xff0c;我们也在把人变笨。 不长脑的机器和不思考的人没什么两样&…

工作利器:三种简单方法将PPT转换成PDF

PDF是一种常用的文件格式&#xff0c;适合数据传输和阅读。在工作中&#xff0c;有时我们需要将PPT文件转换为PDF格式以方便使用。下面是几种将PPT转换为PDF的方法&#xff0c;其中方法二将修改为使用记灵在线工具进行转换。 方法一&#xff1a;直接将文件导出为PPT 一般来说…

OpenHarmony3.1安全子系统-签名系统分析

介绍 应用签名系统主要负责鸿蒙hap应用包的签名完整性校验&#xff0c;以及应用来源识别等功能。 子系统间接口&#xff1a; 应用完整性校验模块给其他模块提供的接口&#xff1b;完整性校验&#xff1a; 通过验签&#xff0c;保障应用包完整性&#xff0c;防篡改&#xff1b;…

postman接口自动化测试

Postman除了前面介绍的一些功能&#xff0c;还有其他一些小功能在日常接口测试或许用得上。今天&#xff0c;我们就来盘点一下&#xff0c;如下所示&#xff1a; 1.数据驱动 想要批量执行接口用例&#xff0c;我们一般会将对应的接口用例放在同一个Collection中&#xff0c;然…

上周,又劝退了10几个...

最近看了很多简历&#xff0c;很多候选人年限不小&#xff0c;但是做的都是一些非常传统的项目&#xff0c;想着也不能通过简历就直接否定一个人&#xff0c;何况现在大环境越来 越难&#xff0c;大家找工作也不容易&#xff0c;于是就打算见一见。 在沟通中发现&#xff0c;由…

chatgpt赋能Python-openpyxl_批注

Openpyxl 批注简介 Openpyxl 是一个用于操作 Microsoft Excel 文件的 Python 库&#xff0c;它提供了许多方便的功能来读取、写入和修改 Excel 文件。其中一个功能是批注&#xff0c;可以在单元格中添加注释或提醒。 Openpyxl 批注的具体用途 Openpyxl 批注在 Excel 工作表中…

应届毕业生第一份C++程序员工作看重什么?我聊聊自己的看法

大家知道应届毕业生的第一份工C程序员工作看重什么&#xff0c;我相信那位同学可能他那个想去做的时候就说啊&#xff0c;因为第二家公司是世界杯公司吗&#xff0c;是单休哈对吧&#xff0c;而且待遇没有另一家高。我相信我们大部分人其实都看中一个&#xff0c;是累不累啊&am…

(浙大陈越版)数据结构 第三章 树(上) 3.1 树和树的表示

目录 3.1.1 引子&#xff08;顺序查找&#xff09; 什么是树 查找 3.1.2 引子 二分查找例子(BinarySearch) 二分查找 3.1.3 引子 二分查找实现 二分查找代码 二分查找的启示 3.1.4 树的定义 一些基本术语&#xff1a; 3.1.5 树的表示 3.1.1 引子&#xff08;顺序查找…

学习Se-net和Sk-net 附网络简单代码(pytorch)

&#xff08;一&#xff09;Se-net的原理和思路     Se-net严格来说是一个小结构&#xff0c;它可以直接插入已有的网络结构中&#xff0c;帮助原有结构获得更好的效果&#xff0c;如插入Resnet网络中。 Se-net的整个流程如下&#xff1a;     &#xff08;1&#xf…

chatgpt赋能Python-opencv_python打开摄像头

OpenCV Python打开摄像头&#xff1a;一种简单的图像处理方式 OpenCV是一种常用的图像处理库&#xff0c;可以用Python编程轻松进行图像和视频处理。其中&#xff0c;打开摄像头也是OpenCV中常用的一种方法。在这篇文章中&#xff0c;我们将介绍OpenCV Python打开摄像头的原理…

chatgpt赋能Python-numpy开根

NumPy开根 在科学计算中&#xff0c;开根运算是一个经常需要进行的操作&#xff0c;它非常有用&#xff0c;可以用来求解方程、计算距离或者简单地将数据压缩成更容易理解的形式等。NumPy是一个强大的库&#xff0c;被广泛地用于Python编程中&#xff0c;它提供了用于开根的特…

chatgpt赋能Python-mofan_python

Mofan Python&#xff1a;一个优秀的入门编程网站 介绍 Mofan Python 是一个致力于帮助人们快速入门 Python 编程的网站。该网站提供了各种编程资源&#xff0c;包括 Python 相关的教程、实例、项目&#xff0c;以及机器学习和深度学习课程等。它的特点在于提供了详细的代码解…

华为OD机试真题 Java 实现【投篮大赛】【2023Q1 100分】

一、题目描述 你现在是一场采用特殊赛制投篮大赛的记录员。 这场比赛由若于回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分&#xff0c;比赛开始时&#xff0c;记录是空白的。 你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[i] 是你需要记录…

FastDDS安全机制1 - 安全配置

背景 OMG组织对于DDS的安全机制有着对应的定义&#xff0c;其定义在DDS-SECURITY文档中。 这其中主要包含了对应的身份认证、访问控制、通信加密和审计相关的插件。 资料来源&#xff1a;DDS-SECURITY 其实也主要保护了通信过程中的相关安全风险。 资料来源&#xff1a;DDS-S…

轻松保护文档安全:三种实用的PDF加密方法

在我们的日常工作中&#xff0c;经常会使用到PDF格式的文件。为了保护版权和隐私&#xff0c;有时候我们需要对文档进行加密处理。那么&#xff0c;如何对PDF进行加密呢&#xff1f;今天我将为大家介绍几种方法&#xff0c;其中包括记灵在线工具、迅捷PDF编辑器和Speedpdf。 方…