一. 新增菜品
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对象进行返回就需要使用对象的拷贝,以及查出来的分类需要判空操作。
版权归原作者 爪哇斗罗 所有, 如有侵权,请联系我们删除。