苍穹外卖-day04

news/2025/3/25 10:51:46/文章来源:https://www.cnblogs.com/heiml/p/18788055

day-04

25-3-20

新增套餐

需求分析&设计

image-20250321201126408

业务规则

  • 套餐名称唯一
  • 套餐必须属于某个分类
  • 套餐必须包含菜品
  • 名称、分类、价格、图片为必填项
  • 添加菜品窗口需要根据分类类型来展示菜品
  • 新增的套餐默认为停售状态

接口设计(共涉及到4个接口):

  • 根据类型查询分类(已完成)
  • 根据分类id查询菜品
  • 图片上传(已完成)
  • 新增套餐

根据菜品分类id查询菜品

image-20250321202033532

新增套餐

image-20250321202135100

代码开发

1. 根据菜品分类查询菜品

controller

    /***根据分类id查询菜品** @return*///TODO 新增套餐时  搜索框里输入菜品名称进行搜索,前端好像没有写接口,日后再议@GetMapping("/list")@ApiOperation("根据分类id查询菜品")public Result<List<Dish>> list(Long categoryId){log.info("分类id查询菜品: id={}",categoryId);List<Dish> list = dishService.list(categoryId);return Result.success(list);}

service

//接口/*** 根据分类id查询菜品** @param categoryId* @return*/List<Dish> list(Long categoryId);//impl/*** 根据分类id查询菜品** @param categoryId* @return*/public List<Dish> list(Long categoryId) {Dish dish = Dish.builder().categoryId(categoryId).status(StatusConstant.ENABLE).build();return dishMapper.list(dish);}

mapper

/*** 动态条件查询菜品** @param dish* @return*/List<Dish> list(Dish dish);

dishMapper.xml

    <!--动态条件查询菜品--><select id="list" resultType="com.sky.entity.Dish">select * from dish<where><if test="name != null">and name like concar('%',#{name},'%')</if><if test="categoryId !=null ">and category_id = #{categoryId}</if><if test="status !=null ">and status = #{status}</if></where>order by create_time desc</select>

2.新增套餐

controller

   //SetmealController/*** 新增套餐及其对应菜品关系数据** @param setmealDTO* @return*/@PostMapping@ApiOperation("新增套餐")public Result save(@RequestBody SetmealDTO setmealDTO){log.info("新增套餐:{}",setmealDTO);setmealService.saveWithDish(setmealDTO);return Result.success();}

service

//接口void saveWithDish(SetmealDTO setmealDTO);//imple/*** 新增套餐及其对应菜品关系数据* 1.向套餐表中插入数据* 2.向套餐菜品关系表中插入多条数据** @param setmealDTO*/@Transactionalpublic void saveWithDish(SetmealDTO setmealDTO) {Setmeal setmeal = new Setmeal();BeanUtils.copyProperties(setmealDTO,setmeal);//向套餐表插入一条数据setmealMapper.insert(setmeal);//向套餐菜品关系表插入多条数据List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();//判断是否有菜品数据,并将套餐id填充if(setmealDishes != null && setmealDishes.size() > 0){setmealDishes.forEach(dish -> dish.setSetmealId(setmeal.getId()));//批量插入setmealDishMapper.insertBatch(setmealDishes);}}

mapper

 //SetmealMapper/*** 新增套餐** @param setmeal*/@Insert("insert into setmeal (category_id, name, price, description, image, create_time, update_time, create_user, update_user)" +"values (#{categoryId},#{name},#{price},#{description},#{image},#{createTime},#{updateTime},#{createUser},#{updateUser})")@AutoFill(value = OperationType.INSERT)void insert(Setmeal setmeal);//SetmealDishMapper/*** 批量插入套餐菜品关系数据** @param setmealDishes*/void insertBatch(List<SetmealDish> setmealDishes);

xml

    <!--批量插入套餐菜品关系数据--><insert id="insertBatch">insert into setmeal_dish (setmeal_id, dish_id,name,price,copies) values<foreach collection="list" item="sd" separator="," >(#{sd.setmealId}, #{sd.dishId},#{sd.name},#{sd.price},#{sd.copies})</foreach></insert>

遇到的错误

动态sql参考:https://mybatis.net.cn/dynamic-sql.html

参考2:https://blog.csdn.net/weixin_44825912/article/details/130433302

新增套餐 批量插入套餐菜品关系数据 动态sql写错,还是不够熟练

//报错信息
### SQL: insert into setmeal_dish (setmeal_id, dish_id,name,price,copies) values          (              ?, ?,?,?,?)          ,             ?, ?,?,?,?)          ,             ?, ?,?,?,?)          ,             ?, ?,?,?,?)          ,             ?, ?,?,?,?)          ,             ?, ?,?,?,?)          )动态sql写错。
继续学习动态sql<!--批量插入套餐菜品关系数据--><insert id="insertBatch">insert into setmeal_dish (setmeal_id, dish_id,name,price,copies) values<foreach collection="list" item="sd" open="("  separator="," close=")">#{sd.setmealId}, #{sd.dishId},#{sd.name},#{sd.price},#{sd.copies})</foreach><!--修正后--><insert id="insertBatch">insert into setmeal_dish (setmeal_id, dish_id,name,price,copies) values<foreach collection="list" item="sd" separator="," >(#{sd.setmealId}, #{sd.dishId},#{sd.name},#{sd.price},#{sd.copies})</foreach></insert>

功能测试&提交

功能一:根据菜品分类查询菜品完成

image-20250322104258089

功能二:新增套餐

image-20250322115658577

测试成功提交

套餐分页查询

需求分析&设计

业务规则:

  • 根据套餐名称查询套餐
  • 新增套餐 (已完成)
  • 分页查询菜单
    • 需要关联分类表展示套餐分类id对应的分类名
    • 分页按照创建时间倒序排列

image-20250322194036538

接口设计:

image-20250322194234889

代码开发

controller


//SetmealController/*** 套餐分页查询** @param setmealPageQueryDTO* @return*/@GetMapping("/page")@ApiOperation("套餐分页查询")public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO){log.info("套餐分页查询信息:{}",setmealPageQueryDTO);PageResult pageResult =  setmealService.pageQuery(setmealPageQueryDTO);return Result.success(pageResult);}

service

//接口
PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);//impl/*** 套餐分页查询** @param setmealPageQueryDTO* @return*/public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {PageHelper.startPage(setmealPageQueryDTO.getPage(),setmealPageQueryDTO.getPageSize());Page<SetmealVO> page = setmealMapper.pageQuery(setmealPageQueryDTO);return new PageResult(page.getTotal(),page.getResult());}

mapper

    /*** 分页查询套餐** @param setmealPageQueryDTO* @return*/Page<SetmealVO> pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);

xml

    <!--分页查询--><select id="pageQuery" resultType="com.sky.vo.SetmealVO">select s.*,c.name as categoryName from setmeal s left outer join category c on s.category_id=c.id<where><if test="name!=null and name!=''">and s.name like concat('%',#{name},'%')</if><if test="categoryId!=null">and s.category_id=#{categoryId}</if><if test="status!=null and status!=''">and s.status=#{status}</if></where>order by s.create_time desc</select>

功能测试&提交

测试成功&提交

image-20250322202547643

删除套餐

需求分析&设计

业务规则:

  • 要求实现批量删除
  • 只有停售的套餐才可以被删除
  • 删除套餐要同步批量删除菜品套餐关系表中的对应数据

image-20250322205308466

接口设计:

image-20250322205902414

代码开发

补充:Objects.equals(a,b)的作用与原理

1.作用:

  • 用于安全的比较两个对象是否相等,避免NullpointerException

  • 源码image-20250323114930275


controller

    /*** 批量删除套餐** @param ids* @return*/@DeleteMapping@ApiOperation("批量删除套餐")public Result delete(@RequestParam List<Long> ids){log.info("删除套餐:{}", ids);setmealService.deleteBatch(ids);return Result.success();}

service

//接口/*** 根据id批量删除套餐** @param ids*/void deleteBatch(List<Long> ids);//impl/*** 批量删除套餐** @param ids*/@Override@Transactionalpublic void deleteBatch(List<Long> ids) {//1.判断当前套餐是否在启售中for (Long id : ids){//根据套餐id查询套餐信息Setmeal setmeal = setmealMapper.getByid(id);//判断状态不为空,并且等于1 为启售中    启售中菜品不能删除if (Objects.equals(setmeal.getStatus(), StatusConstant.ENABLE)) {throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);}}//2.删除套餐表中对应的数据setmealMapper.deleteByIds(ids);//3.删除套餐菜品关系表中对应数据setmealDishMapper.deleteBySetmealIds(ids);}

mapper

//setmealMapper/*** 根据套餐id查询套餐信息** @param id* @return*/@Select("select * from setmeal where id = #{id}")Setmeal getByid(Long id);/*** 删除套餐表中对应数据** @param ids*/void deleteByIds(List<Long> ids);//setmealDishMapper/*** 根据套餐id批量删除套餐菜品关系数据** @param setmealIds*/void deleteBySetmealIds(List<Long> setmealIds);

sr.xml

<!--setmealMapepr.xml--><!--删除套餐表中对应数据--><delete id="deleteByIds">delete from setmeal where id in<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach></delete><!--setmealDishMapper-->
<!--根据套餐id批量删除套餐菜品关系数据--><delete id="deleteBySetmealIds">delete from setmeal_dish where setmeal_id in<foreach collection="setmealIds" item="setmealId" open="(" separator="," close=")">#{setmealId}</foreach></delete>

功能测试&提交

测试成功

image-20250323005051809

修改套餐

需求分析&设计

业务规则:

  • 套餐信息回显,根据套餐id查询套餐
  • 接受前端DTO对象并修改
image-20250323120809520

接口设计:

image-20250323120757172 image-20250323120922106

遇到错误错误

回显数据时不能回显套餐关联的菜品信息, 猜测可能是新增套餐时没有新增套餐和菜品关联关系的原因

setmeal_dish

image-20250323135733332

果然是因为前面新增套餐时有bug,没有将套餐和菜品之间的关联关系插入

,现在回显还是有问题,但属于回显的问题---->查询,OK

果不其然,因为前面以为是回显查询sql出了问题,所有修改了sql,后面忘记了,现在修改回去就好了


代码开发

修改业务 & 回显数据:

SetmealController

	/*** 回显套餐数据** @param id* @return*/@GetMapping("/{id}")@ApiOperation("根据id查询套餐数据")public Result<SetmealVO> getById(@PathVariable Long id){log.info("根据id查询套餐数据:id={}", id);SetmealVO setmealVO = setmealService.getByIdWithDish(id);return Result.success(setmealVO);}    @PutMapping@ApiOperation("修改套餐")public Result update(@RequestBody SetmealDTO setmealDTO){log.info("修改套餐:{}",setmealDTO);setmealService.update(setmealDTO);return Result.success();}

SetmealSerivce

    /*** 根据id查询套餐和菜品的关联关系** @param id* @return*/SetmealVO getByIdWithDish(Long id);  	/*** 根据id查询套餐和套餐菜品关系** @param id* @return*/public SetmealVO getByIdWithDish(Long id){//根据id查询套餐基本信息Setmeal setmeal = setmealMapper.getById(id);SetmealVO setmealVO = new SetmealVO();//根据id查询套餐和菜品的关联关系List<SetmealDish> setmealDishes = setmealDishMapper.getBySetmealId(id);//将基本信息拷贝到VO中,给VO设置套餐和菜品的关联关系BeanUtils.copyProperties(setmeal,setmealVO);setmealVO.setSetmealDishes(setmealDishes);return setmealVO;}/*** 修改套餐** @param setmealDTO*/void update(SetmealDTO setmealDTO);//impl/*** 修改套餐** @param setmealDTO*/@Transactionalpublic void update(SetmealDTO setmealDTO) {Setmeal setmeal = new Setmeal();BeanUtils.copyProperties(setmealDTO, setmeal);//1、修改套餐表,执行updatesetmealMapper.update(setmeal);//套餐idLong setmealId = setmealDTO.getId();//2、删除套餐和菜品的关联关系,操作setmeal_dish表,执行deletesetmealDishMapper.deleteBySetmealId(setmealId);List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();setmealDishes.forEach(setmealDish -> {setmealDish.setSetmealId(setmealId);});//3、重新插入套餐和菜品的关联关系,操作setmeal_dish表,执行insertsetmealDishMapper.insertBatch(setmealDishes);}

mapper

//setmealDishMapper/*** 根据id查询套餐和菜品的关联关系** @param setmealId* @return*/@Select("select * from setmeal_dish where setmeal_id = #{setmealId}")List<SetmealDish> getBySetmealId(Long setmealId);/*** 删除套餐关联id** @param id*/@Delete("delete from setmeal_dish where setmeal_id = #{id}")void deleteBySetmealId(Long id);//setmealMapper/***根据套餐id查询套餐信息** @param id* @return*/@Select("select * from setmeal where id = #{id}")Setmeal getById(Long id);/*** 修改套餐** @param setmeal*/@AutoFill(OperationType.UPDATE)void update(Setmeal setmeal);<!--动态 xml--><update id="update">update setmeal<set><if test="categoryId!=null">category_id=#{categoryId},</if><if test="name!=null and name!=''">name=#{name},</if><if test="price!=null">price=#{price},</if><if test="image!=null and image!=''">image=#{image},</if><if test="description!=null and description!=''">description=#{description},</if><if test="updateTime!=null">update_time=#{updateTime},</if><if test="updateUser!=null and updateUser!=''">update_user=#{updateUser},</if><if test="status!=null">status=#{status},</if></set>where id=#{id}</update>

功能测试&提交

测试成功& 提交

image-20250323162622519

启售停售套餐

需求分析&设计

  • 菜品停售会关联套餐停售
  • 而套餐可以随意停售,不会影响单独菜品

所以我应该先写套餐停售


  • 可以对状态为起售的套餐进行停售操作,可以对状态为停售的套餐进行起售操作
  • 起售的套餐可以展示在用户端,停售的套餐不能展示在用户端
  • 起售套餐时,如果套餐内包含停售的菜品,则不能起售

接口设计:

image-20250323163600199

代码开发

controller

    /*** 套餐启用 & 禁用** @param status* @param id* @return*/@PostMapping("/status/{status}")@ApiOperation("套餐启用禁用")public Result status(@PathVariable Integer status,Long id){log.info("修改套餐为{}状态",status == StatusConstant.ENABLE ? "启售" : "停售");setmealService.startOrStop(status,id);return Result.success();}

service

    /*** 套餐启售停售** @param status* @param id*/void startOrStop(Integer status,Long id);/*** 套餐启售停售** @param status* @param id*/@Overridepublic void startOrStop(Integer status, Long id) {//起售套餐时,判断套餐内是否有停售菜品,有停售菜品提示"套餐内包含未启售菜品,无法启售"//如果前端传过来要修改的状态为启售,那么我要继续检查该套餐里的菜品是否含有禁售菜品,如果有,抛出异常 +++if(status == StatusConstant.ENABLE){//select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = ?//查询该套餐包含的所有菜品 ,然后检查菜品状态是否为禁售List<Dish> dishList = dishMapper.getBySetmealId(id);if(dishList != null && dishList.size() > 0){dishList.forEach(dish -> {if(StatusConstant.DISABLE == dish.getStatus()){throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);}});}}//+++ 如果没有 就修改状态Setmeal setmeal = Setmeal.builder().id(id).status(status).build();setmealMapper.update(setmeal);}

mapper

//DishMapper/***根据id查询菜品信息** @param id* @return*/@Select("select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = #{id}")List<Dish>  getBySetmealId(Long id);//setmealMapper/*** 修改套餐** @param setmeal*/@AutoFill(OperationType.UPDATE)void update(Setmeal setmeal);//服用之前的修改套餐SetmealMapper的update即可<!--动态 xml--><update id="update">update setmeal<set><if test="categoryId!=null">category_id=#{categoryId},</if><if test="name!=null and name!=''">name=#{name},</if><if test="price!=null">price=#{price},</if><if test="image!=null and image!=''">image=#{image},</if><if test="description!=null and description!=''">description=#{description},</if><if test="updateTime!=null">update_time=#{updateTime},</if><if test="updateUser!=null and updateUser!=''">update_user=#{updateUser},</if><if test="status!=null">status=#{status},</if></set>where id=#{id}</update>

功能测试&提交

image-20250323170550576

补充一个菜品停售

  • 因为写了套餐停售才能写菜品停售

controller

    /*** 启用或禁用菜品* @param status* @param id* @return*/@PostMapping("/status/{status}")@ApiOperation("启用或禁用菜品")public Result status(@PathVariable Integer status,Long id){dishService.startOrStop(status,id);return Result.success();}

service

    /*** 菜品启售 禁售** @param status* @param id*/void startOrStop(Integer status, Long id);   /*** 启用或禁用菜品** @param status* @param id*/@Overridepublic void startOrStop(Integer status, Long id) {Dish dish = Dish.builder().status(status).id(id).build();dishMapper.update(dish);}

mapper

    /*** 根据id更新菜品** @param dish*/@AutoFill(OperationType.UPDATE)void update(Dish dish);<!--根据菜品id 动态修改菜品--><update id="update">update dish<set><if test="name!=null and name!=''">name=#{name},</if><if test="categoryId!=null">category_id=#{categoryId},</if><if test="price!=null">price=#{price},</if><if test="image!=null and image!=''">image=#{image},</if><if test="description!=null and description!=''">description=#{description},</if><if test="updateTime!=null">update_time=#{updateTime},</if><if test="updateUser!=null and updateUser!=''">update_user=#{updateUser},</if><if test="status!=null">status=#{status},</if></set>where id=#{id}</update>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/904274.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提示词工程师自白:我如何用一个技巧解放自己的生产力

“在AI时代的交响乐中,提示词工程师是默默无闻却至关重要的指挥家,用精心编织的语言指引大模型这个智能巨兽创造出人类思维的奇迹。” AI粉嫩特攻队,2025年3月22日。 自从新的生产范式诞生以来,我的工作中多了一项新身份——提示工程师。 在不同的大语言模型之间穿梭,寻求…

20244123 实验一《Python程序设计》实验报告

20244123 2024-2025-2 《Python程序设计》实验x报告 课程:《Python程序设计》 班级: 2441 姓名: 邓淑怀 学号:20244123 实验教师:王志强 实验日期:2025年3月20日 必修/选修: 公选课 1.实验内容 (1)熟悉Python开发环境; (2)练习Python运行、调试技能; (3)编写程序…

https://liweinlp.com/13092 总结

https://liweinlp.com/13092一段话总结 大型语言模型(LLMs)的“黑箱”特性(因复杂参数和层级结构导致决策过程难以追踪)引发信任、伦理和监管挑战。“Logits Lens”技术通过解码模型中间层的隐藏状态,将其转化为词元(token)的概率分布,直观展示模型在不同层级对下一个词…

RabbitMQ的用户详解以及maven导入

一.RabbitMQ的角色分类 1:none:不能访问management plugin2:management:查看自己相关节点信息列出自己可以通过AMQP登入的虚拟机 查看自己的虚拟机节点 virtual hosts的queues,exchanges和bindings信息 查看和关闭自己的channels和connections 查看有关自己的虚拟机节点vir…

第四周第三章3.1—3.5

3.1 initial_weight = 50 print("年份\t地球体重(kg)\t月球体重(kg)") for year in range(1, 11): earth_weight = initial_weight + (year - 1) * 0.5 moon_weight = earth_weight * 0.165 print(f"{year}\t\t{earth_weight:.2f}\t\t{moon_weight:.2f}")3…

PolarCTF网络安全2025春季个人挑战赛 WRITE UP

1-1 可老师签到 本题思路如下: 提示“发送的内容为双写字符串拼接”公众号发送flagflag即可1-2 find 本题思路如下: 把表格文件当压缩包解压,找到flag.xlsx\xl\worksheets\sheet1.xml 发现里面存了数据,于是考虑把数据格子上色以得到flag 先将xml文件处理以获得纯数据代码:…

Go红队开发—CLI框架(一)

CLI命令行工具编写基础学习(一)。CLI开发框架 命令行工具开发,主要是介绍开发用到的包,集成了一个框架,只要学会了基本每个人都能开发安全工具了。 该文章先学flags包,是比较经典的一个包,相比后面要学习的集成框架这个比较自由比较细化点,自定义可能高一些,后续会学到一…

WSL2安装Ubuntu

本文是介绍如何使用任意一台Windows主机借助WSL2创建Ubuntu虚拟系统并开放局域网内SSH连接的操作指南!先决条件拥有能够访问github.com的网络环境; 必须运行 Windows 10 版本 2004 及更高版本(内部版本 19041 及更高版本)或 Windows 11版本;安装WSL2 以管理员身份运行Powe…

人工‘够好就行’智能(AGEI)就快来了!

比尔弗兰克斯 前言:本文作者的观点是在真正的通用人工智能(AGI)到来之前,一种“够好就行”的人工智能(AGEI)就已经足以引发我们原本担心 AGI 才会带来的重大社会变革、正面效益,甚至潜在危机。 换句话说: AI 不需要达到像人类一样全面智能的程度; 只要在足够多的任务上…

List集合--java进阶day09

1.List集合以下面的例子来解释存储有序和存储重复如上图,我们是怎么添加这些字符串的,打印的时候就是按照这个顺序打印的--存取有序 并且“张三”出现了两次,也存入了两次--存储重复 因为List有索引,所以该接口有关于索引的独特的api..1.remove注意事项 List有两个remove方…

Pydantic字段级校验:解锁@validator的12种应用

title: Pydantic字段级校验:解锁@validator的12种应用 date: 2025/3/23 updated: 2025/3/23 author: cmdragon excerpt: Pydantic校验系统支持通过pre验证器实现原始数据预处理,在类型转换前完成字符清洗等操作。格式验证涵盖正则表达式匹配与枚举值约束,确保护照编号等字…