一、回顾与概述
昨天我们使用AOP与反射完成了公共字段填充通知,进阶CRUD的操作完成了菜品模块。今天的任务是无课程讲解,自己通过查看产品模型和接口文档,分析表与表之间的关系,实战完成套餐模块。
二、套餐模块
1.产品模型与接口概览
套餐分页查询支持套餐名称、分类、状态进行模糊查询、查出来的数据按照创建时间倒序排列,删除操作时套餐在售不可删除,起售时套餐如果套餐内存在停售菜品则无法起售。
2.新增套餐
(1)接口文档
通过分析新增套餐页面可以大致明白这一功能由五个接口完成。
1.套餐分类的选择框实质上是查询了套餐所有种类
2.套餐图片上传
3.添加菜品的时候可以按照分类显示出对应菜品供我们选择
4.添加菜品时右上角有个搜索框提供按照菜品名称模糊查询
5.最终点保存的新增套餐大接口
p1.分类模块根据类型查询分类type=2就是查询套餐类型(已完成)
p2.上传文件(OSS云服务CommonController已完成)
p3.根据分类id查询对应所有菜品
p4.根据菜品名字模糊查询
p5.保存新增套餐
(2)Controller层
1.根据分类id查询所有菜品,帮助我们添加菜品的时候按照不同分类回显对应的菜品。
DishController层
2.根据菜品名字模糊查询,当你写完该功能的三层代码后,一运行你会发现报错了。原因在于根据菜品名字模糊查询与上面的根据分类id查询菜品使用了相同的请求方式和Path路径,这说明它们两个接口本质上是一个,因此我们需要对根据分类id查询菜品接口进行修改,不再使用categoryId作为唯一请求参数,而是由扩展性更强的DishDTO替代,这样前端不管传菜品的什么属性都可以封装进去。
DishController层
3.保存新增套餐
SetmealController
(3)Service层
直接调用mapper返回对应菜品即可
新增套餐逻辑分为两步,第一步是把套餐基本信息插入到setmeal表中 ,第二步是把与套餐关联的菜品插入setmeal_dish表中 ,当然在插入第二张表之前套餐的每个菜品都要关联套餐ID ,这个套餐ID我们并不知道,必须要在setmealMapper的insert方法上加**@Options注解**,取到数据库中自增的套餐ID赋值回参数setmeal中,然后就可以通过setmeal.getId()拿到套餐ID了。
(4)Mapper层
根据菜品属性查询菜品,由于用DTO封装的,前端传啥参数我就按照这个参数动态查询即可,除了名字是like模糊查询其他都是等值查询。
新增操作别忘了加AOP注解填充公共字段
3.套餐分页查询
(1)接口文档
分析接口文档和页面可以发现请求参数categoryId、name、status都是可选参数,代表着分页查询可以通过这三个参数进行动态查询。
(2)Controller层
Result里面封装PageResult,传参用自定义SetmealPageQueryDTO类封装,调用service层返回PageResult即可,分页查询惯用模板。
(3)Service层
依旧分页查询模板,设置分页参数,调用Mapper接口,返回new出来的PageResult,唯一有变化的就是调用Mapper接口需要想想Page泛型里面是什么类,相当于就是查出来显示的每行数据用啥封装合适,自定义一个SetmealVO返回前端。
(4)Mapper层
根据前端所传属性编写动态SQL语句查询数据,需要注意前端返回的data里面有categoryName字段,而在setmeal表中没有这个字段因此需要联表查询,此外还需要注意Mybatis的自动封装条件,需要把category表的name字段查出来取别名categoryName,跟封装类该字段名字保持相同,才可以封装到SetmealVO中。根据产品原型要求,分页查询的结果按照创建时间倒序。
4.删除套餐
(1)接口文档
请求参数ids后端用集合接收,必须要加@ResutParam注解。分析产品原型,批量删除套餐的时候如果套餐在售是不准删除的,其次分析业务逻辑如果setmeal这张表对应套餐删了,那么setmeal_dish这张表被删套餐对应的菜品也要删掉。
(2)Controller层
使用@RequestParam注解集合接收参数
(3)Service层
删除逻辑总共三步,第一步先判断要批量删除的套餐里面有没有套餐是在售状态 的,如果有那就停止删除,抛出自定义异常。第二步就是根据套餐id先批量删除setmeal表 里面的套餐数据。第三步就是根据套餐id删除setmeal_dish表里面对应套餐id的数据。
(4)Mapper层
根据套餐id查找套餐各个字段封装回SetmealVO类中,方便复用,这里就是取状态判断即可
setmealMapper里面的批量删除方法,注意动态SQL的书写即可。
setmealDishMapper的批量删除方法同上
5.修改套餐
(1)接口文档
修改操作依旧涉及到两个基本接口对应的回显、修改两步。
分析修改页面发现套餐菜品处的修改操作十分复杂,不仅涉及到删除操作,还可以继续新增,甚至可以修改份数。因此我们此处的修改套餐菜品操作选择把原本该套餐关联的菜品先全部清空,再重新插入确定好的数据(setmeal和setmealDish两张表都需要操作)。此外回显操作时套餐菜品还需要另写一个SQL语句再setmeal_dish表查关联的菜品,主要涉及到setmeal和setmealDish两张表
(2)Controller层
根据id查询套餐注意是路径参数,修改套餐请求参数为json。
(3)Service层
回显操作中,setmealMapper负责查找套餐基本信息回显,setmealDishMapper则负责查找该套餐关联菜品的基本信息回显,最后全部封装到SetmealVO返回到前端。
更新套餐操作中,主要分为三大步。
第一步更新套餐基本信息,也就是setmeal表中的数据,所需要的东西已经在SetmealDTO里面了,这里之所以要new一个Setmeal类进行浅拷贝,主要是考虑到DTO里面的数据不全像更新时间更新人都没有,因此使用Setmeal作为参数,配合AOP技术实行公共字段填充。
第二步删除所有套餐关联的所有菜品信息,这一步就是在处理setmeal_dish表里面的数据,需要根据套餐ID清空全部数据。
第三步就是新增最终修改确定好的套餐关联的所有菜品信息,这个东西已经封装到DTO传给我们了,我们取到这个SetmealDish数据集合后必须要先把所有数据都和该套餐id都关联起来,不然到时候往setmeal_dish表插入数据会因为每条数据都没有SetmealId而报错,当然这个套餐ID在DTO里面也已经封装了。
(4)Mapper层
1.根据套餐ID查询套餐基本信息回显
2.根据套餐ID查询它关联的所有菜品信息
3.更新套餐的基本信息
4.根据套餐ID把与该套餐关联的菜品信息清空
5.重新插入该套餐关联的菜品信息
6.套餐起售停售
(1)接口文档
起售停售注意起售前需要检查套餐中所有菜品中是否存在停售菜品。套餐内如果有停售菜品,则套餐无法上架。
(2)Controller层
注意有一个路径参数还有一个普通参数。
(3)Service层
分析接口文档和产品原型,可知起售停售逻辑就两步,第一步判断操作为起售操作,那就进入if分支进一步判断这个套餐的所有菜品是否存在停售菜品 (这里需要联表查询 ,因为菜品的状态只有在dish表中才有),如果存在那就抛出自定义异常。第二步就是更新套餐起售停售状态 ,这里用一个Setmeal封装 是因为光有status和id属性做更新操作是不够的,还需要更新updateTime和updateUser,所以配合AOP增强填充公共字段,需要new一个setmeal。
(4)Mapper层
根据套餐ID查询该套餐关联的所有菜品信息,返回到Lish<Dish>里面,重点取到每个Dish的status,判断是否存在停售的菜品。
根据ID更新套餐状态,复用之前的update方法。
三、总结
Day4没有视频讲解,是彻头彻尾的实战,有了前两天的视频讲解内容的积累以及两日的博客复盘,其实第四天的任务内容并不难,真正需要注意的反而是根据前端请求、接口文档和产品原型去分析每个接口怎么设计,怎么实现复用,还有一些比较细节的需求一开始没有看见,但是在接口的不断编写中,对业务的熟悉程度也不断增加,我也在这个过程中发现了之前自己没有注意到的需求,把之前漏掉的功能点一处处补上。写技术博客复盘真的是不错的习惯,每次都相当于重新自己独立设计一遍接口然后进行开发,对业务的熟悉正是在不断地分析接口作用实现的。


















































