(一)新增
controller层思路:
- 调用service处理
- 响应处理结果
@PostMapping
public R<String> save(@RequestBody DishDto dishDto){dishService.saveWithFlavors(dishDto);return R.success("新增成功!");
}
service层
public interface DishService extends IService<Dish> {void saveWithFlavors(DishDto dishDto);
}
serviceImpl层思路:
注意:由于新增菜品操作了两张表 进行了2个写操作,要保证插入菜品基本信息和口味信息同时成功 新增菜品才成功 所以需要添加事务管理,在方法上打上@Transactional注解以及在启动类上开启事务注解驱动管理即可
- 检查菜品名称不能重复
- 保存菜品基本信息到菜品口味表dish,可以直接传dishDto对象 因为dishDto继承了Dish 插入时只会根据Dish类中有的属性设置插入字段的值 多余的字段会自动忽略
- 获取菜品id MyBatisPlus中当完成了新增操作之后,会自动的将生成的id赋值到对象的主键属性上
- 保存菜品口味信息到菜品口味表dish_flavor
- 获取菜品口味信息列表
- 为当前的菜品口味设置关联的菜品id dish_id字段
@Transactional
@Override
public void saveWithFlavors(DishDto dishDto) {LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();wrapper.eq(Dish::getName,dishDto.getName());Integer count = dishDao.selectCount(wrapper);if (count>0){throw new CustomException(0,"菜品名称'"+dishDto.getName()+"'已经存在");}dishDao.insert(dishDto);Long dishDtoId = dishDto.getId();List<DishFlavor> flavors = dishDto.getFlavors();flavors.stream().forEach(flavor->{flavor.setDishId(dishDtoId);dishFlavorDao.insert(flavor);});
}
(二)分页查询
controller层
@GetMapping("/page")
public R<Page<DishDto>> page(@RequestParam(defaultValue="1") Integer page, @RequestParam(defaultValue="10") Integer pageSize, String name){//1.调用service处理Page<DishDto> dishPage = dishService.findPage(page,pageSize,name);//2.响应处理结果return R.success(dishPage);
}
service层
public interface DishService extends IService<Dish> {Page<DishDto> findPage(Integer page, Integer pageSize, String name);
}
serviceImpl层
注意事项:
问题1:分页查询时 菜品图片没有显示
原因:没有将测试数据中 菜品对应图片放入 D:\reggie\目录下
解决:将资源中提供的图片资源放入D:\reggie\目录下
问题2:分页查询时 菜品所属的分类名称没有展示
原因:前端页面进行菜品所属分类展示时 需要的是菜品分类名称categoryName 而我们查询菜品表返回的数据只有菜品所属分类id 没有分类名称
解决:
- 分页查询返回菜品列表数据的同时 在每一条菜品数据中应该包含菜品的所属分类名称categoryName
- 将每一个菜品dish对象中的数据 封装到dishDto对象中,并且设置dishDto对象的categoryName属性即可实现前端的正常展示
- 响应的数据 Page<Dish>> ==》 Page<DishDto>>
- 原来响应的给前端的数据是 R<Page<Dish>> -----> Page<Dish>:封装分页相关的数据 records:当前页数据List<Dish> total:总条数
- 现在我们要响应给前端的数据是 R<Page<DishDto>> ----> Page<DishDto>:封装分页相关的数据 records:当前页数据 List<DishDto> total:总条数
实际实现步骤:
- 从dishPage对象中获取当前页数据列表 dishList List<Dish>
- 遍历dishList集合 将集合中的每一个dish对象中的数据赋值到DishDto对象中,并且为DishDto对象的categoryName属性赋值
- 在遍历dishList集合时,将每一个新创建出来的dishDto对象 存入到dishDtoList集合中 【这样就得到当前页要显示的数据集合了】
- 将当前页数据集合dishDtoList和总条数封装到dishDtoPage对象中返回即可
@Override
public Page<DishDto> findPage(Integer page, Integer pageSize, String name) {//0.配置分页查询拦截器 【已经配置好了】//1.封装分页参数page和pageSize到Page对象中Page<Dish> dishPage = new Page<>(page, pageSize);//2.设置分页查询条件 根据菜品名称name进行模糊查询LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();wrapper.like(name!=null&&name.length()>0,Dish::getName,name);//3.调用selectPage方法 传入Page对象和wrapper对象完成分页查询dishDao.selectPage(dishPage,wrapper);//完善代码:响应Page<DishDto>//a:创建Page<DishDto> dishDtoPage对象Page<DishDto> dishDtoPage = new Page<>();//b.将dishPage中的当前页数据集合List和总条数设置到dishDtoPage对象//当前页数据列表ListList<Dish> dishList = dishPage.getRecords();//b1:将dishList中的每一个元素dish对象转为DishDto 存入到List<DishDto> dishDtoList中List<DishDto> dishDtoList = new ArrayList<>();for (Dish dish : dishList) {//创建DishDto对象DishDto dishDto = new DishDto();//将dish对象中的菜品信息赋值到dishDto对象中,要注意源对象的属性和目标对象的属性要一致BeanUtils.copyProperties(dish,dishDto);//查询当前菜品所属的分类名称Category category = categoryDao.selectById(dish.getCategoryId());dishDto.setCategoryName(category.getName());//将dishDto对象放入到DishDtoList集合中dishDtoList.add(dishDto);}//将当前页要显示的数据 设置到dishDtoPage对象的records属性上dishDtoPage.setRecords(dishDtoList);//b2:将总条数设置到dishDtoPage对象的total属性上dishDtoPage.setTotal(dishPage.getTotal());//4.返回Page对象【Page对象中包含当前页数据集合List和总条数】return dishDtoPage;
}
(三)ID条件查询
controller层
@GetMapping("/{id}")
public R<DishDto> getById(@PathVariable Long id){//1.调用service处理DishDto dishDto = dishService.getByIdWithFlavors(id);//2.响应处理结果return R.success(dishDto);
}
service层
public interface DishService extends IService<Dish> {DishDto getByIdWithFlavors(Long id);
}
serviceImpl层思路:
- 根据菜品id查询菜品的基本信息数据
- 根据菜品id查询菜品的口味信息数据
- 将菜品的基本信息及其口味信息封装到DishDto对象中返回
- 使用Spring提供的BeanUtils工具类 可以将一个源对象的属性数据赋值到一个目标对象属性上 要求属性名称前后一致
- 返回结果
//根据id查询菜品信息
@Override
public DishDto getByIdWithFlavors(Long id) {Dish dish = dishDao.selectById(id);LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();wrapper.eq(DishFlavor::getId,id);List<DishFlavor> flavors = dishFlavorDao.selectList(wrapper);DishDto dishDto = new DishDto();BeanUtils.copyProperties(dish,dishDto);dishDto.setFlavors(flavors);return dishDto;
}
(四)修改
controller层
@PutMapping
public R<String> update(@RequestBody DishDto dishDto){//1.调用service处理dishService.updateWithFlavors(dishDto);//2.响应处理结果return R.success("修改成功!");
}
service层
public interface DishService extends IService<Dish> {void updateWithFlavors(DishDto dishDto);
}
serviceImpl层思路:
- 判断菜品修改后要保存的菜品名称不能和其他的菜品名称相同
- 修改菜品dish表中的菜品基本信息
- 修改菜品口味dish_flavor表中的菜品口味信息
- 获取当前菜品id
- 删除当前菜品对应的所有口味信息 根据菜品口味对应的菜品id进行删除
- 将当前菜品修改后的口味信息保存到dish_flavor表中
- 获取当前菜品修改后的口味信息列表
- 循环遍历 要设置口味的id置为null,口味关联的dish_id要设置为当前菜品id,口味的id置为null,口味关联当前菜品dish_id,保存到dish_flavor表中。
@Transactional
@Override
public void updateWithFlavors(DishDto dishDto) {LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();wrapper.eq(Dish::getName,dishDto.getName());wrapper.ne(Dish::getId,dishDto.getId());Integer count = dishDao.selectCount(wrapper);if (count>0){throw new CustomException(0,"菜品名称'"+dishDto.getName()+"'已存在!");}dishDao.updateById(dishDto);Long dishId = dishDto.getId();LambdaQueryWrapper<DishFlavor> flavorLambdaQueryWrapper = new LambdaQueryWrapper<>();flavorLambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);dishFlavorDao.delete(flavorLambdaQueryWrapper);List<DishFlavor> flavors = dishDto.getFlavors();flavors.stream().forEach(flavor->{flavor.setId(null);flavor.setDishId(dishId);dishFlavorDao.insert(flavor);});
}
(五)删除
controller层
//删除菜品
@DeleteMapping("/{ids}")
public R<String> deleteByIds(@PathVariable Long[] ids){//1.调用service处理dishService.deleteByIds(ids);//2.响应处理结果return R.success("删除成功!");
}
service层
public interface DishService extends IService<Dish> {void deleteByIds(Long[] ids);
}
serviceImpl层思路:
- 判断ids中是否为null 提示:没有选中要删除的套餐
- 判断要删除的套餐是否处于停售状态 如果处于起售状态:则不能删除 抛出异常提示,根据要删除的套餐id 设置查询条件status=1 进行统计 如果个数大于1,说明存在启售状态的套餐,不能删除
//删除
@Transactional
@Override
public void deleteByIds(Long[] ids) {if (ids==null||ids.length==0){throw new CustomException(0,"没有选中要删除的套餐");}LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();List<Long> idsList = Arrays.asList(ids);wrapper.in(Dish::getId,idsList);List<Dish> dishList = this.list(wrapper);dishList.stream().forEach(dish -> {if (dish.getStatus()==1){throw new CustomException(0,"当前菜品'"+dish.getName()+"'处于启售状态,无法删除!");}Long dishId = dish.getId();LambdaQueryWrapper<DishFlavor> dishFlavorWrapper = new LambdaQueryWrapper<>();dishFlavorWrapper.eq(DishFlavor::getDishId,dishId);dishFlavorDao.delete(dishFlavorWrapper);this.removeById(dish.getId());});}
(六)启用 && 禁用 (批量)
controller层
//启用禁用
@PostMapping("/status/{status}")
public R<String> updateEmp(@PathVariable Integer status,@RequestParam List<Long> ids){dishService.updateDishStatus(status, ids);return R.success("修改成功!");
}
service层
public interface DishService extends IService<Dish> {void updateDishStatus(Integer status,List<Long> ids);
}
serviceImpl层
//批量启售禁售
@Override
public void updateDishStatus(Integer status, List<Long> ids) {LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();wrapper.in(ids!=null,Dish::getId,ids);List<Dish> lists = this.list(wrapper);lists.stream().forEach(list->{if (list!=null){list.setStatus(status);this.updateById(list);}});
}
(七)根据菜品分类id和菜品名称查询菜品列表数据
本次偷懒,全在在controller层实现
- 调用service处理,得到菜品列表数据
- 创建wrapper对象
- 设置查询条件,菜品所属分类id、菜品名称、菜品状态status
- 添加查询条件 当status不为null时,设置查询启售的菜品列表数据
- 调用list方法查询
- 循环遍历List<Dish>集合,将菜品的基本信息封装到DishDto对象中
- 还需要根据菜品的分类id和菜品id查询出所属分类名称和菜品的口味信息封装到DishDto对象中
- 将DishDto存入到List集合中 返回
- 响应数据
//根据菜品分类id和菜品名称查询菜品列表数据
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish){LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();wrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId()); //当分类id不为null 根据分类id进行查询wrapper.like(dish.getName()!=null,Dish::getName,dish.getName()); //当菜品名称name不为null,根据菜品名称进行模糊查询wrapper.eq(dish.getStatus()!=null,Dish::getStatus,dish.getStatus()); //查询启售的菜品List<Dish> list = dishService.list(wrapper);List<DishDto> dishDtoList = list.stream().map((item)->{DishDto dishDto = new DishDto();BeanUtils.copyProperties(item,dishDto);Category category = categoryService.getById(item.getCategoryId());dishDto.setCategoryName(category==null?"未知":category.getName());LambdaQueryWrapper<DishFlavor> wrapper1 = new LambdaQueryWrapper<>();wrapper1.eq(DishFlavor::getDishId,item.getId());List<DishFlavor> flavors = dishFlavorService.list(wrapper1);dishDto.setFlavors(flavors);return dishDto;}).collect(Collectors.toList());return R.success(dishDtoList);
}