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

目录

菜品分页查询

需求分析和设计

代码开发

设计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模块中

java 复制代码
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模块中

java 复制代码
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分页查询方法:

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

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

java 复制代码
 //菜品分页查询
    PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);
Service层实现类

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

java 复制代码
 //菜品分页查询
    @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 方法:

java 复制代码
 //菜品分页查询
    Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);

在 DishMapper.xml 中编写SQL:

java 复制代码
 <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中创建方法:

java 复制代码
//菜品批量删除
    @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方法:

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

在DishServiceImpl中实现deleteBatch方法:

java 复制代码
  //菜品批量删除

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

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

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

java 复制代码
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

java 复制代码
<?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:

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

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

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

性能优化

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

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

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

java 复制代码
 //根据菜品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中

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

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

在DishMapper.xml中

java 复制代码
 <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中创建方法:

java 复制代码
 //根据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方法:

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

在DishServiceImpl中实现getByIdWithFlavor方法:

java 复制代码
//根据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:

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

修改菜品实现

Controller层

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

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

在DishService接口中声明updateWithFlavor方法:

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

在DishServiceImpl中实现updateWithFlavor方法:

java 复制代码
//根据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方法:

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

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

java 复制代码
 <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>

功能测试

相关推荐
2301_811274318 分钟前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
武子康19 分钟前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康21 分钟前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言28 分钟前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
界面开发小八哥35 分钟前
更高效的Java 23开发,IntelliJ IDEA助力全面升级
java·开发语言·ide·intellij-idea·开发工具
草莓base1 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
Allen Bright1 小时前
maven概述
java·maven
Ljw...1 小时前
表的增删改查(MySQL)
数据库·后端·mysql·表的增删查改
编程重生之路1 小时前
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
java·spring boot·后端
薯条不要番茄酱1 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea