苍穹外卖Day03——总结3

发布于:2024-03-01 ⋅ 阅读:(99) ⋅ 点赞:(0)

前期文章

文章标题 地址
苍穹外卖Day01——总结1 https://lushimeng.blog.csdn.net/article/details/135466359
苍穹外卖Day01——解决总结1中存在的问题 https://lushimeng.blog.csdn.net/article/details/135473412
苍穹外卖Day02——总结2 https://lushimeng.blog.csdn.net/article/details/135484126
苍穹外卖Day02——解决总结2中存在的问题 https://lushimeng.blog.csdn.net/article/details/136242268

1. 菜品管理效果图

分页查询界面

在这里插入图片描述

新增菜品界面

在这里插入图片描述

2. 新增菜品模块

新增菜品界面

在这里插入图片描述

业务规则:

  • 菜品名称必须是唯一的
  • 菜品必须属于某个菜品分类categorey下,不能单独存在
  • 新增菜品时可以根据情况选择菜品的口味
  • 每个菜品必须对应一张图片

接口需求

  • 查询菜品分类接口
  • 上传图片接口,这里把图片存在在阿里云OOS
  • 保存菜品接口

前两个接口都比较简单,这里需要介绍一下第三个接口:保存菜品接口,由于一个菜品包含多个口味,多以在插入菜品dish的同时还需要把菜品的口味插入到另一个独立的dish_flavour中。这里在插入菜品dish的时候需要使用主键回填的技术,这样才能为每个口味添加对应的dish_id。

DishServiceImpl

/**
     * 菜品添加
     * @param dishDTO
     */
    @Transactional
    public void saveWithFlavor(DishDTO dishDTO) {
        // 1. 添加菜品
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        dishMapper.saveDish(dish);

        // 主键回填技术, 用于后续给每个口味添加对应的菜品dish_id
        Long dishId = dish.getId();

        // 2. 添加菜品的口味
        List<DishFlavor> flavors = dishDTO.getFlavors();
        flavors.forEach(flavor -> flavor.setDishId(dishId));
        dishFlavorMapper.saveBatch(flavors); // 批量添加
    }

DishMapper.xml

    <!--主键回填-->
    <insert id="saveDish" useGeneratedKeys="true" keyProperty="id">
        insert into dish (name, category_id, price, image, description, create_time, update_time, create_user,update_user, status)
        values
               (#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}, #{status})
    </insert>

3. 分页查询模块

分页查询效果图

在这里插入图片描述

分页查询不是很熟悉,这里就详细的介绍一下整体的流程。

步骤一:确定前端传递的参数以及后端需要返回的数据格式

前端传递参数

@Data
public class DishPageQueryDTO implements Serializable {
    private int page;
    private int pageSize;
    private String name;
    //分类id
    private Integer categoryId;
    //状态 0表示禁用 1表示启用
    private Integer status;
}

后端返回数据格式

/**
 * 封装分页查询结果
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
    private long total; //总记录数
    private List records; //当前页数据集合
}

步骤二:确定接口

DishController

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

DishServiceImpl

这里使用PageHelper插件。首先调用startPage方法,开始分页查询;然后获取查询信息,这里返回统一为Page page;然后根据获取的page得到查询总数以及每条查询信息集合。下面代码是固定的套路,记住即可。

    /**
     * 分页查询
     * @param dishPageQueryDTO
     * @return
     */
    public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        // 开始分页查询
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        // 获取分页查询page, 固定写法
        Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
        long total = page.getTotal();  // 获取总数
        List<DishVO> records = page.getResult();  // 获取内容
        return new PageResult(total, records);
    }

DishMapper.xml:

这里使用了多表联查:“select d.* , c.name as categoryName from dish d left outer join category c on d.category_id = c.id

给表起别名、表字段起别名以及联合查询。要特别学一下这种思想,经常在分页查询中用到。

    <select id="pageQuery" parameterType="com.sky.dto.DishPageQueryDTO" 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>

4. 删除菜品模块

删除菜品

在这里插入图片描述

业务规则:

  • 可以一次删除一个菜品,也可以批量删除菜品,因为一次删除多个菜品包括一次删除一个,所以只需要一个接口即可:一次删除多个。
  • 起售中的菜品不能删除
  • 被套餐关联的菜品不能删除
  • 删除菜品后,关联的口味数据也需要删除掉

上述接口比较简单,只需要弄清业务规则即可,特别是在删除菜品的时候需要该菜品是否有关联项,能否不考虑其他部分直接删除。

5. 修改菜品模块

修改菜品界面:

在这里插入图片描述

在修改菜品的时候需要回显菜品相关信息,该页面共涉及4个接口。

接口:

  • 根据id查询菜品
  • 根据类型查询分类
  • 文件上传
  • 修改菜品

修改注意事项

  • 菜品数据回显
  • 修改菜品时候可能会修改菜品口味,正确的做法是删除该菜品对应的所有口味,然后插入新传入的口味信息
  • 云资源浪费为题。如果换了图片原来的图片还存储在云上会造成资源浪费,猜测后续使用redis删除无用的照片,插入到云上的图片也存入到redis中,redis上的图片信息和运算的图片信息进行比对,然后删除多余文件信息,减少云资源浪费

6. 总结

收获

  1. CURD: Controller -> service -> serviceImpl -> mapper -> mapper.xml
  2. 前端到后端数据:XXXDTO, 后端返回给前端数据:XXXVO;
  3. 分页查询有自己一套模板,使用分页插件,记住就行;
  4. 业务逻辑分析:
    • 删除模块:在删除的时候需要考虑该信息是否关联其他信息?
    • 修改模块:如果该信息关联其他模块,修改了该信息其他信息是否会修改,原来的信息怎么办?

补充内容

内容1:字段填充,由于每个模块都含有创建时间、创建人、更新时间和更新人信息,每次都需要setXXX进行设置,太繁琐,提出了字段填充。本项目提出的字段填充使用到: AOP, 反射,主键等技术;

内容2:@RequestBody、@RequestParam、@PathVariable用法区别;

内容3:阿里云云存储。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到