基于Springboot外卖系统12:删除菜品套餐类别+修改套餐类别信息

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

1. 删除分类


1.1 需求分析


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


a3f715e468724315b719be3ea458b12a.png


1.2 前端页面分析


在前端页面中,点击 "删除" 按钮,就会触发定义的方法,然后往服务端发送异步请求,并传递参数id,执行删除分类操作。


ac09c0d57e1e406aaed5466a51958e1a.png


删除操作的具体执行流程如下:


1). 点击删除,页面发送ajax请求,将参数(id)提交到服务端


2). 服务端Controller接收页面提交的数据并调用Service删除数据


3). Service调用Mapper操作数据库


fcc9e072c2ff4a7ba67b037407d5d057.png


从上述的分析中,可以得到请求的信息如下:


请求 说明
请求方式 DELETE
请求路径 /category
请求参数 ?id=1395291114922618881


1.3 改进思路分析


删除分类数据需要检查删除的分类是否关联了菜品或者套餐,所以需要进行功能完善。完善后的逻辑为:


  • 根据当前分类的ID,查询该分类下是否存在菜品,如果存在,则提示错误信息


  • 根据当前分类的ID,查询该分类下是否存在套餐,如果存在,则提示错误信息


  • 执行正常的删除分类操作


那么在这里又涉及到两张表结构 dish(菜品表) 和 setmeal(套餐表)。具体的表结构如下:


ccc799fab91e4b5ea93e83fa730dbd43.png


738bc0b9384c414fb99964d6c86bc085.png


1.4 准备工作


1.4.1 Dish菜品实体类


package com.itheima.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
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;
}


1.4.2 Setmeal套餐实体类


package com.itheima.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
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;
}


1.4.3. Mapper接口DishMapper和SetmealMapper


DishMapper


package com.itheima.reggie.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.Dish;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DishMapper extends BaseMapper<Dish> {
}


SetmealMapper


package com.itheima.reggie.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.Setmeal;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
}


1.4.3 Service接口DishService和SetmealService


DishService


package com.itheima.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.Dish;
public interface DishService extends IService<Dish> {
}


SetmealService


package com.itheima.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.Setmeal;
public interface SetmealService extends IService<Setmeal> {
}


1.5 代码实现


1). 创建自定义异常


在业务逻辑操作过程中,如果遇到一些业务参数、操作异常的情况下,直接抛出此异常。


package com.itheima.reggie.common;
import javax.xml.crypto.dsig.spec.XSLTTransformParameterSpec;
/**
 * Description: 自定义业务异常类
 * @date 2022/8/16 10:32
 */
public class CustomException extends RuntimeException{
    public CustomException(String message){
        super(message);
    }
}


2). 在CategoryService中扩展remove方法


package com.itheima.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.Category;
public interface CategoryService extends IService<Category> {
    public void remove(Long id);
}


3). 在CategoryServiceImpl中实现remove方法


package com.itheima.reggie.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.Setmeal;
import com.itheima.reggie.mapper.CategoryMapper;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishService;
import com.itheima.reggie.service.SetmealService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * Description: 类别业务层接口
 * @version 1.0
 * @date 2022/8/15 13:55
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    @Autowired
    private DishService dishService ;
    @Autowired
    private SetmealService setmealService;
    @Override
    /**@Description: 根据id删除分类,删除之前需要判定是否关联菜品
     * @version v1.0
     * @author LiBiGo
     * @date 2022/8/16 10:20
     */
    public void remove(Long id) {
        // A.查询当前分类是否关联菜品,关联则抛出业务异常类
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 添加查询条件,根据id查询
        dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
        int count1 = dishService.count(dishLambdaQueryWrapper);
        if (count1 > 0){
            // 已关联菜品,抛出异常
            throw new CustomException("当前分类下关联了菜品,不能删除");
        }
        // B.查询当前分类是否关联套餐,关联则抛出业务异常类
        LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 添加查询条件,根据id查询
        setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
        int count2 = setmealService.count(setmealLambdaQueryWrapper);
        if (count2 > 0){
            // 已关联套餐,抛出异常
            throw new CustomException("当前分类下关联了套餐,不能删除");
        }
        // 均无关联,则删除
        super.removeById(id);  // 父类实现了最基本的根据id查询的删除,所以直接调用就行
    }
}


那么在上述的业务逻辑中,当分类下关联的有菜品或者套餐时,在业务代码中抛出了自定义异常,会被异常处理器捕获,只需要在异常处理器中捕获这一类的异常,然后给页面返回对应的提示信息即可。


4). 在GlobalExceptionHandler中处理自定义异常


在全局异常处理器中增加方法,用于捕获自定义的异常 CustomException


package com.itheima.reggie.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.sql.SQLIntegrityConstraintViolationException;
/**
 * Description: 全局异常处理器
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class})// 处理@RestController、@Controller的函数异常 //指定拦截那些类型的控制器;
@ResponseBody   //将方法的返回值 R 对象转换为json格式的数据, 响应给页面;
@Slf4j
public class GlobalExceptionHandler {
    /**@Description: 异常处理方法
     * @author LiBiGo
     * @date 2022/8/12 17:46
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class) // 处理指定异常类
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error(ex.getMessage());
        //Duplicate entry '299067' for key 'idx_username'
        if(ex.getMessage().contains("Duplicate entry")){
            String[] split = ex.getMessage().split(" "); //提取重复字段,即哪个用户名重复 从0开始第2个即为用户名
            String msg = split[2] + "已存在";
            return R.error(msg);
        }
        return R.error("未知错误");
    }
    @ExceptionHandler(CustomException.class) // 处理自定义业务异常类
    public R<String> exceptionHandler(CustomException ex){
        log.error(ex.getMessage());
        return R.error(ex.getMessage());
    }
}


5). 改造CategoryController的delete方法


注释掉原有的代码,在delete方法中直接调用categoryService中自定义的remove方法。


package com.itheima.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
 * Description: 分类管理
 */
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
    @Autowired
    private CategoryService categoryService;
    /**@Description: 新增分类
     * @author LiBiGo
     * @date 2022/8/15 14:05
     */
    @PostMapping
    public R<String> save(@RequestBody Category category){
        log.info("category:{}",category);
        categoryService.save(category);
        return R.success("新增分类成功");
    }
    @GetMapping("/page")
    public R<Page> page(int page,int pageSize){
        /**@Description: 分页查询
         * @author LiBiGo
         * @date 2022/8/15 14:21
         */
        // 分页构造
        Page<Category> pageinfo = new Page<>(page,pageSize);
        // 构造条件构造器对象
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper();
        // 添加排序条件,根据sore进行排序
        queryWrapper.orderByAsc(Category::getSort);
        // 进行分页查询
        categoryService.page(pageinfo,queryWrapper);
        return R.success(pageinfo);
    }
    @DeleteMapping
    public R<String> delete(Long id){
        /**@Description: 根据id删除分类
         * @author LiBiGo
         * @date 2022/8/16 9:58
         */
        log.info("删除分类,id为{}",id);
        categoryService.remove(id);
        return R.success("分类信息删除成功");
    }
    @PutMapping
    public  R<String> update(@RequestBody Category category){
        /**@Description: 根据id修改分类信息
         * @author LiBiGo
         * @date 2022/8/16 10:49
         */
        log.info("根据id修改分类信息:{}",category);
        categoryService.updateById(category);
        return R.success("修改分类成功");
    }
}


2. 修改分类


2.1 需求分析


在分类管理列表页面点击修改按钮,弹出修改窗口,在修改窗口回显分类信息并进行修改,最后点击确定按钮完成修改操作。


24ce70cb840b4966922a3f4497071179.png


2.2 前端页面分析


这里面大家会发现,修改功能我们还没有实现,但是当点击 "修改" 按钮的时候,我们并没有开发根据ID查询数据,进行页面回显的功能,但是页面的分类数据确实回显回来了。这是怎么做到的呢,我们来解析一下前端的代码实现(前端代码已经实现):


07ce80c27f914860bc07e67dc2a36e2f.png



那么回显这一步的操作前端已经实现,我们就只需要开发一个方法,修改操作的方法即可。我们可以通过浏览器来抓取一下修改操作的请求信息,如图:


a6119e90fe5b4f298ddccc72664201fd.png


具体的请求信息,整理如下:


请求 说明
请求方式 PUT
请求路径 /category
请求参数 {id: "1399923597874081794", name: "超值午餐", sort: 0}


2.3 代码实现


html页面中相关的代码都已经提供好了,我们已经分析了请求的信息,接下来就可以来创建服务端的CategoryController方法update方法。


【见上一个代码块,已集成】

目录
相关文章
|
2月前
|
开发框架 前端开发 网络协议
Spring Boot结合Netty和WebSocket,实现后台向前端实时推送信息
【10月更文挑战第18天】 在现代互联网应用中,实时通信变得越来越重要。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为客户端和服务器之间的实时数据传输提供了一种高效的解决方案。Netty作为一个高性能、事件驱动的NIO框架,它基于Java NIO实现了异步和事件驱动的网络应用程序。Spring Boot是一个基于Spring框架的微服务开发框架,它提供了许多开箱即用的功能和简化配置的机制。本文将详细介绍如何使用Spring Boot集成Netty和WebSocket,实现后台向前端推送信息的功能。
557 1
|
3月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的服装商城管理系统
基于Java+Springboot+Vue开发的服装商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的服装商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
191 2
基于Java+Springboot+Vue开发的服装商城管理系统
|
12天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
69 13
|
1月前
|
XML Java 数据库连接
SpringBoot集成Flowable:打造强大的工作流管理系统
在企业级应用开发中,工作流管理是一个核心组件,它能够帮助我们定义、执行和管理业务流程。Flowable是一个开源的工作流和业务流程管理(BPM)平台,它提供了强大的工作流引擎和建模工具。结合SpringBoot,我们可以快速构建一个高效、灵活的工作流管理系统。本文将探讨如何将Flowable集成到SpringBoot应用中,并展示其强大的功能。
225 1
|
1月前
|
Java Spring 容器
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
119 3
|
1月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
存储 安全 Java
打造智能合同管理系统:SpringBoot与电子签章的完美融合
【10月更文挑战第7天】 在数字化转型的浪潮中,电子合同管理系统因其高效、环保和安全的特点,正逐渐成为企业合同管理的新宠。本文将分享如何利用SpringBoot框架实现一个集电子文件签字与合同管理于一体的智能系统,探索技术如何助力合同管理的现代化。
115 4
|
2月前
|
前端开发 Java Apache
SpringBoot实现电子文件签字+合同系统!
【10月更文挑战第15天】 在现代企业运营中,合同管理和电子文件签字成为了日常活动中不可或缺的一部分。随着技术的发展,电子合同系统因其高效性、安全性和环保性,逐渐取代了传统的纸质合同。本文将详细介绍如何使用SpringBoot框架实现一个电子文件签字和合同管理系统。
114 1
|
3月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
239 3
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
|
2月前
|
文字识别 安全 Java
SpringBoot3.x和OCR构建车牌识别系统
本文介绍了一个基于Java SpringBoot3.x框架的车牌识别系统,详细阐述了系统的设计目标、需求分析及其实现过程。利用Tesseract OCR库和OpenCV库,实现了车牌图片的识别与处理,确保系统的高准确性和稳定性。文中还提供了具体的代码示例,展示了如何构建和优化车牌识别服务,以及如何处理特殊和异常车牌。通过实际应用案例,帮助读者理解和应用这一解决方案。