当前位置:网站首页>瑞吉外卖项目:新增菜品与菜品分页查询
瑞吉外卖项目:新增菜品与菜品分页查询
2022-07-31 11:03:00 【过的很好谢谢】
目录
一. 新增菜品
1.1 需求分析
后台系统可以管理菜品信息,通过新增功能来添加新的菜品,在添加菜品时需要选择当前菜品所属的菜品分类。
此外还需要上传菜品图片,在移动端会按照菜品分类来展示对应的菜品信息。
1.2 数据模型
设计两张表菜品表与菜品口味表,添加某个菜品的口味做法时,需要加入菜品口味表中。
菜品表(dish)
菜品口味表(dish_flavor)
在开发代码之前,需要梳理一下新增菜品时前端页面和服务端的交互过程:
- 页面(backend/page/food/add.html)发送aiax请求,请求服务端获取菜品分类数据并展示到下拉框中
- 页面发送请求进行图片上传,请求服务端将图片保存到服务器
- 页面发送请求进行图片下载,将上传的图片进行回显
- 点击保存按钮,发送ajax请求,将菜品相关数据以ison形式提交到服务端
dishFlavor.java
package com.itheima.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 菜品口味
*/
@Data
public class DishFlavor implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//菜品id
private Long dishId;
//口味名称
private String name;
//口味数据list
private String value;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
//是否删除
private Integer isDeleted;
}
填好所需数据发的添加菜品的mock格式如下:
{
"name": "test1",
"price": 1200,
"code": "",
"image": "bbbf37f0-00c1-4dff-8825-b79506ad33cf.jpg",
"description": "sdfg",
"status": 1,
"categoryId": "1397844263642378242",
"flavors": [
{
"name": "辣度",
"value": "["不辣","微辣","中辣","重辣"]",
"showOption": false
},
{
"name": "温度",
"value": "["热饮","常温","去冰","少冰","多冰"]",
"showOption": false
}
]
}
**注意:**在Dish(这里)这个对象中并没有封装口味对象,所以我们需要对上面的JSON数据重新封装。
DishDTO.java
package com.itheima.reggie.dto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class DishDto extends Dish {
/** 菜品口味*/
private List<DishFlavor> flavors = new ArrayList<>();
private String categoryName;
private Integer copies;
}
什么是DTO?
Data Transfer Object,数据传输对象,用于展示层与服务层之间的数据传输
1.3代码实现
DishServiceImpl.java中添加如下代码:
package com.itheima.reggie.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author jektong
* @date 2022年05月10日 20:15
*/
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
@Resource
private DishFlavorService dishFlavorService;
/**
* 新增菜品,同时插入菜品对应的口味数据
* @param dishDto
*/
@Override
@Transactional
public void saveWithFlover(DishDto dishDto) {
// 保存菜品基本信息到菜品表dish
this.save(dishDto);
// 获取菜品ID
Long dishId = dishDto.getId();
List<DishFlavor> flavors = dishDto.getFlavors();
// 菜品ID设置进口味中
flavors = flavors.stream().map((item)->{
item.setDishId(dishId);
return item;
}).collect(Collectors.toList());
// 菜品口味数据保存
dishFlavorService.saveBatch(flavors);
}
}
由于以上代码涉及多次对数据库的操作,所以需要加上注解:
@Transactional并需要在启动类上开启事务注解@EnableTransactionManagement才可生效
package com.itheima.reggie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author tongbing
* @date 2022/4/21
*/
@Slf4j
@SpringBootApplication
@ServletComponentScan
@EnableTransactionManagement
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class,args);
log.info("reggie======>启动成功");
}
}
DishController调用:
package com.itheima.reggie.controller;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author jektong
* @date 2022年05月16日 22:22
*/
@RestController
@Slf4j
@RequestMapping("/dish")
public class DishController {
@Resource
private DishService dishService;
/**
* 新增菜品,同时插入菜品对应的口味数据
* @param dishDto
* @return R<String>
*/
@PostMapping
public R<String> save(@RequestBody DishDto dishDto){
log.info("DishDTO===>{}",dishDto);
dishService.saveWithFlover(dishDto);
return R.success("菜品添加成功");
}
}
二. 菜品分页查询
2.1 需求分析
分页展示菜品数据如下图:
交互流程
- 页面(backend/page/food/listhtml)发送ajax请求,将分页查询参数(page,pageSize,name)提交到服务端,获取分页数据
- 页面发送请求,请求服务端进行图片下载,用于页面图片展示
开发菜品信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。
2.2 代码编写
DishController代码:
@GetMapping("/page")
public R<Page> page(int page, int pageSize,String name){
log.info("page={},pageSize={},name={}", page, pageSize, name);
// 构造分页构造器
Page<Dish> pageInfo = new Page(page, pageSize);
// 因为前端需要展示分类的名称,所以封装成DishDto对象
Page<DishDto> dishDtoPage = new Page(page, pageSize);
// 构造条件
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper();
queryWrapper.like(StringUtils.isNotEmpty(name), Dish::getName, name);
// 添加排序
queryWrapper.orderByDesc(Dish::getUpdateTime);
// 执行查询
dishService.page(pageInfo, queryWrapper);
// 进行对象拷贝,去除之前已经查出来的集合
BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");
List<Dish> records = pageInfo.getRecords();
List<DishDto> list = records.stream().map((item)->{
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item,dishDto);
// 获取categoryId
Long categoryId = item.getCategoryId();
// 给categoryName赋值
Category category = categoryService.getById(categoryId);
// 需要对查出来的分类做判断可能有的菜品没有分类
if(category!=null){
dishDto.setCategoryName(category.getName());
}
return dishDto;
}).collect(Collectors.toList());
dishDtoPage.setRecords(list);
return R.success(dishDtoPage);
}
以上代码需要注意的是需要展示分类的名称,所以封装成DishDto对象进行返回就需要使用对象的拷贝,以及查出来的分类需要判空操作。
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦
边栏推荐
- Intranet Penetration Learning (IV) Domain Lateral Movement - SMB and WMI Service Utilization
- 初识二叉搜索树
- Unix知识:shell详细解读
- 分布式事务Seata详细使用教程
- “chmod 777-R 文件名”什么意思?
- Make your own dataset in FCN and train it
- What does "chmod 777-R filename" mean?
- 《JUC并发编程 - 高级篇》06 - 共享模型之不可变(不可变类的设计 | 不可变类的使用 | 享元模式)
- KVM虚拟化作业
- SQLServer2019 installation (Windows)
猜你喜欢
新人学习小熊派华为iot介绍
Make your own dataset in FCN and train it
3D激光SLAM:LeGO-LOAM论文解读---完整篇
Redis缓存面临的缓存穿透问题
darknet 源码阅读笔记-01-activation_kernels.cu
「MySQL」- 基础增删改查
What does "chmod 777-R filename" mean?
ASP.NET 身份认证框架 Identity(一)
MySQL 的几种碎片整理方案总结(解决delete大量数据后空间不释放的问题)
准确率(Accuracy)、精度(Precision)、召回率(Recall)和 mAP 的图解
随机推荐
LeetCode 1161.最大层内元素和:层序遍历
【GORM】存取数组/自定义类型数据
解决报错TypeError:unsupported operand type(s) for +: ‘NoneType‘ and ‘str‘
【LeetCode】Day108-和为 K 的子数组
7 天找个 Go 工作,Gopher 要学的条件语句,循环语句 ,第3篇
Three ways of single sign-on
【LeetCode】242. 有效的字母异位词
Detailed explanation of SQL stored procedures
unity-shader-2
Intranet Penetration Learning (IV) Domain Lateral Movement - SMB and WMI Service Utilization
【LeetCode】387. 字符串中的第一个唯一字符
“带薪划水”偷刷阿里老哥的面经宝典,三次挑战字节,终成正果
In half a month, MySQL has been consolidated again, and a tens of thousands of words "super hard core" article has been sorted out!
准确率(Accuracy)、精度(Precision)、召回率(Recall)和 mAP 的图解
Redis - Basics
双链表的插入和删除
WSL2安装.NET 6
Sql优化总结!详细!(2021最新面试必问)
Implement the popup component
【软件工程之美 - 专栏笔记】33 | 测试工具:为什么不应该通过QQ/微信/邮件报Bug?