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


    1. 删除分类

    1.1 需求分析

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

    1.2 前端页面分析

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

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

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

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

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

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

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

    1.3 改进思路分析

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

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

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

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

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

    1.4 准备工作

    1.4.1 Dish菜品实体类

    1. package com.itheima.reggie.entity;
    2. import com.baomidou.mybatisplus.annotation.FieldFill;
    3. import com.baomidou.mybatisplus.annotation.IdType;
    4. import com.baomidou.mybatisplus.annotation.TableField;
    5. import com.baomidou.mybatisplus.annotation.TableId;
    6. import lombok.Data;
    7. import java.io.Serializable;
    8. import java.math.BigDecimal;
    9. import java.time.LocalDateTime;
    10. /**
    11. 菜品
    12. */
    13. @Data
    14. public class Dish implements Serializable {
    15. private static final long serialVersionUID = 1L;
    16. private Long id;
    17. //菜品名称
    18. private String name;
    19. //菜品分类id
    20. private Long categoryId;
    21. //菜品价格
    22. private BigDecimal price;
    23. //商品码
    24. private String code;
    25. //图片
    26. private String image;
    27. //描述信息
    28. private String description;
    29. //0 停售 1 起售
    30. private Integer status;
    31. //顺序
    32. private Integer sort;
    33. @TableField(fill = FieldFill.INSERT)
    34. private LocalDateTime createTime;
    35. @TableField(fill = FieldFill.INSERT_UPDATE)
    36. private LocalDateTime updateTime;
    37. @TableField(fill = FieldFill.INSERT)
    38. private Long createUser;
    39. @TableField(fill = FieldFill.INSERT_UPDATE)
    40. private Long updateUser;
    41. }

    1.4.2 Setmeal套餐实体类 

    1. package com.itheima.reggie.entity;
    2. import com.baomidou.mybatisplus.annotation.FieldFill;
    3. import com.baomidou.mybatisplus.annotation.IdType;
    4. import com.baomidou.mybatisplus.annotation.TableField;
    5. import com.baomidou.mybatisplus.annotation.TableId;
    6. import lombok.Data;
    7. import java.io.Serializable;
    8. import java.math.BigDecimal;
    9. import java.time.LocalDateTime;
    10. /**
    11. * 套餐
    12. */
    13. @Data
    14. public class Setmeal implements Serializable {
    15. private static final long serialVersionUID = 1L;
    16. private Long id;
    17. //分类id
    18. private Long categoryId;
    19. //套餐名称
    20. private String name;
    21. //套餐价格
    22. private BigDecimal price;
    23. //状态 0:停用 1:启用
    24. private Integer status;
    25. //编码
    26. private String code;
    27. //描述信息
    28. private String description;
    29. //图片
    30. private String image;
    31. @TableField(fill = FieldFill.INSERT)
    32. private LocalDateTime createTime;
    33. @TableField(fill = FieldFill.INSERT_UPDATE)
    34. private LocalDateTime updateTime;
    35. @TableField(fill = FieldFill.INSERT)
    36. private Long createUser;
    37. @TableField(fill = FieldFill.INSERT_UPDATE)
    38. private Long updateUser;
    39. }

    1.4.3. Mapper接口DishMapper和SetmealMapper

    DishMapper

    1. package com.itheima.reggie.mapper;
    2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    3. import com.itheima.reggie.entity.Dish;
    4. import org.apache.ibatis.annotations.Mapper;
    5. @Mapper
    6. public interface DishMapper extends BaseMapper {
    7. }

    SetmealMapper 

    1. package com.itheima.reggie.mapper;
    2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    3. import com.itheima.reggie.entity.Setmeal;
    4. import org.apache.ibatis.annotations.Mapper;
    5. @Mapper
    6. public interface SetmealMapper extends BaseMapper {
    7. }

    1.4.3 Service接口DishService和SetmealService

    DishService

    1. package com.itheima.reggie.service;
    2. import com.baomidou.mybatisplus.extension.service.IService;
    3. import com.itheima.reggie.entity.Dish;
    4. public interface DishService extends IService {
    5. }

    SetmealService 

    1. package com.itheima.reggie.service;
    2. import com.baomidou.mybatisplus.extension.service.IService;
    3. import com.itheima.reggie.entity.Setmeal;
    4. public interface SetmealService extends IService {
    5. }

    1.5 代码实现

    1). 创建自定义异常

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

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

    2). 在CategoryService中扩展remove方法

    1. package com.itheima.reggie.service;
    2. import com.baomidou.mybatisplus.extension.service.IService;
    3. import com.itheima.reggie.entity.Category;
    4. public interface CategoryService extends IService {
    5. public void remove(Long id);
    6. }

    3). 在CategoryServiceImpl中实现remove方法

    1. package com.itheima.reggie.service.impl;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    4. import com.itheima.reggie.common.CustomException;
    5. import com.itheima.reggie.entity.Category;
    6. import com.itheima.reggie.entity.Dish;
    7. import com.itheima.reggie.entity.Setmeal;
    8. import com.itheima.reggie.mapper.CategoryMapper;
    9. import com.itheima.reggie.service.CategoryService;
    10. import com.itheima.reggie.service.DishService;
    11. import com.itheima.reggie.service.SetmealService;
    12. import org.springframework.beans.factory.annotation.Autowired;
    13. import org.springframework.stereotype.Service;
    14. /**
    15. * Description: 类别业务层接口
    16. * @version 1.0
    17. * @date 2022/8/15 13:55
    18. */
    19. @Service
    20. public class CategoryServiceImpl extends ServiceImpl implements CategoryService {
    21. @Autowired
    22. private DishService dishService ;
    23. @Autowired
    24. private SetmealService setmealService;
    25. @Override
    26. /**@Description: 根据id删除分类,删除之前需要判定是否关联菜品
    27. * @version v1.0
    28. * @author LiBiGo
    29. * @date 2022/8/16 10:20
    30. */
    31. public void remove(Long id) {
    32. // A.查询当前分类是否关联菜品,关联则抛出业务异常类
    33. LambdaQueryWrapper dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
    34. // 添加查询条件,根据id查询
    35. dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
    36. int count1 = dishService.count(dishLambdaQueryWrapper);
    37. if (count1 > 0){
    38. // 已关联菜品,抛出异常
    39. throw new CustomException("当前分类下关联了菜品,不能删除");
    40. }
    41. // B.查询当前分类是否关联套餐,关联则抛出业务异常类
    42. LambdaQueryWrapper setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
    43. // 添加查询条件,根据id查询
    44. setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
    45. int count2 = setmealService.count(setmealLambdaQueryWrapper);
    46. if (count2 > 0){
    47. // 已关联套餐,抛出异常
    48. throw new CustomException("当前分类下关联了套餐,不能删除");
    49. }
    50. // 均无关联,则删除
    51. super.removeById(id); // 父类实现了最基本的根据id查询的删除,所以直接调用就行
    52. }
    53. }

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

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

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

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

    5). 改造CategoryController的delete方法

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

    1. package com.itheima.reggie.controller;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    4. import com.itheima.reggie.common.R;
    5. import com.itheima.reggie.entity.Category;
    6. import com.itheima.reggie.service.CategoryService;
    7. import lombok.extern.slf4j.Slf4j;
    8. import org.springframework.beans.factory.annotation.Autowired;
    9. import org.springframework.web.bind.annotation.*;
    10. /**
    11. * Description: 分类管理
    12. */
    13. @RestController
    14. @RequestMapping("/category")
    15. @Slf4j
    16. public class CategoryController {
    17. @Autowired
    18. private CategoryService categoryService;
    19. /**@Description: 新增分类
    20. * @author LiBiGo
    21. * @date 2022/8/15 14:05
    22. */
    23. @PostMapping
    24. public R save(@RequestBody Category category){
    25. log.info("category:{}",category);
    26. categoryService.save(category);
    27. return R.success("新增分类成功");
    28. }
    29. @GetMapping("/page")
    30. public R page(int page,int pageSize){
    31. /**@Description: 分页查询
    32. * @author LiBiGo
    33. * @date 2022/8/15 14:21
    34. */
    35. // 分页构造
    36. Page pageinfo = new Page<>(page,pageSize);
    37. // 构造条件构造器对象
    38. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
    39. // 添加排序条件,根据sore进行排序
    40. queryWrapper.orderByAsc(Category::getSort);
    41. // 进行分页查询
    42. categoryService.page(pageinfo,queryWrapper);
    43. return R.success(pageinfo);
    44. }
    45. @DeleteMapping
    46. public R delete(Long id){
    47. /**@Description: 根据id删除分类
    48. * @author LiBiGo
    49. * @date 2022/8/16 9:58
    50. */
    51. log.info("删除分类,id为{}",id);
    52. categoryService.remove(id);
    53. return R.success("分类信息删除成功");
    54. }
    55. @PutMapping
    56. public R update(@RequestBody Category category){
    57. /**@Description: 根据id修改分类信息
    58. * @author LiBiGo
    59. * @date 2022/8/16 10:49
    60. */
    61. log.info("根据id修改分类信息:{}",category);
    62. categoryService.updateById(category);
    63. return R.success("修改分类成功");
    64. }
    65. }

    2. 修改分类

    2.1 需求分析

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

    2.2 前端页面分析

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

     

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

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

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

    2.3 代码实现

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

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

  • 相关阅读:
    微服务 - Consul集群化 · 服务注册 · 健康检测 · 服务发现 · 负载均衡
    字节跳动流式数据集成基于Flink Checkpoint两阶段提交的实践和优化
    计算机多媒体
    【GUI】-- 07 Icon & ImageIcon、JPanel & JScroll
    机器人制作开源方案 | 棘轮小车
    sqlite基本操作
    GBase 8c V3.0.0数据类型——会话信息函数
    H5逆向之远程RPC
    【PXIE301-211】青翼科技基于PXIE总线的16路并行LVDS数据采集、1路光纤数据收发处理平台
    SpringBoot属性说明与RESTful开发
  • 原文地址:https://blog.csdn.net/qq_39237205/article/details/126361692