目录
1--苍穹外卖-SpringBoot项目介绍及环境搭建 详解-CSDN博客
2--苍穹外卖-SpringBoot项目中员工管理 详解(一)-CSDN博客
3--苍穹外卖-SpringBoot项目中员工管理 详解(二)-CSDN博客
4--苍穹外码-SpringBoot项目中分类管理 详解-CSDN博客
5--苍穹外卖-SpringBoot项目中菜品管理 详解(一)-CSDN博客
6--苍穹外卖-SpringBoot项目中菜品管理 详解(二)-CSDN博客
7--苍穹外卖-SpringBoot项目中套餐管理 详解(一)-CSDN博客
8--苍穹外卖-SpringBoot项目中套餐管理 详解(二)-CSDN博客
9--苍穹外卖-SpringBoot项目中Redis的介绍及其使用实例 详解-CSDN博客
菜品分页查询
需求分析和设计
业务规则:
-
根据页码展示菜品信息
-
每页展示10条数据
-
分页查询时可以根据需要输入菜品名称、菜品分类、菜品状态进行查询
代码开发
设计DTO类
根据菜品分页查询接口定义设计对应的DTO:
在sky-pojo模块中
java
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class DishPageQueryDTO implements Serializable {
private int page;
private int pageSize;
private String name;
//分类id
private Integer categoryId;
//状态 0表示禁用 1表示启用
private Integer status;
}
设计VO类
根据菜品分页查询接口定义设计对应的VO:(在返回的数据中categoryName属于另外一个文件中,需要使用VO转换属性为json,方便前端展示)
在sky-pojo模块中
java
package com.sky.vo;
import com.sky.entity.DishFlavor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DishVO implements Serializable {
private Long id;
//菜品名称
private String name;
//菜品分类id
private Long categoryId;
//菜品价格
private BigDecimal price;
//图片
private String image;
//描述信息
private String description;
//0 停售 1 起售
private Integer status;
//更新时间
private LocalDateTime updateTime;
//分类名称
private String categoryName;
//菜品关联的口味
private List<DishFlavor> flavors = new ArrayList<>();
//private Integer copies;
}
Controller层
根据接口定义创建DishController的page分页查询方法:
java
//菜品分页查询
@GetMapping("/page")
@ApiOperation("菜品分页查询")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){
log.info("菜品分页查询:{}",dishPageQueryDTO);
PageResult pageResult=dishService.pageQuery(dishPageQueryDTO);
return Result.success(pageResult);
}
Service层接口
在 DishService 中扩展分页查询方法:
java
//菜品分页查询
PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);
Service层实现类
在 DishServiceImpl 中实现分页查询方法:
java
//菜品分页查询
@Override
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
Page<DishVO> page= dishMapper.pageQuery(dishPageQueryDTO);
return new PageResult(page.getTotal(),page.getResult());
}
Mapper层
在 DishMapper 接口中声明 pageQuery 方法:
java
//菜品分页查询
Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);
在 DishMapper.xml 中编写SQL:
java
<select id="pageQuery" resultType="com.sky.vo.DishVO">
select d.* ,c.name as categoryName from dish d left outer join category c on d.category_id=c.id
<where>
<if test="name!=null">
and d.name like concat('%',#{name},'%')
</if>
<if test="categoryId!=null">
and d.category_id=#{categoryId}
</if>
<if test="status!=null">
and d.status=#{status}
</if>
</where>
order by d.create_time desc
</select>
功能测试
删除菜品
需求设计和分析
业务规则:
-
可以一次删除一个菜品,也可以批量删除菜品
-
起售中的菜品不能删除
-
被套餐关联的菜品不能删除
-
删除菜品后,关联的口味数据也需要删除掉
代码开发
Controller层
根据删除菜品的接口定义在DishController中创建方法:
java
//菜品批量删除
@DeleteMapping
@ApiOperation("菜品批量删除")
public Result<String> delete(@RequestParam List<Long> ids){
//@RequestParam注解使用mvc框架,可以获取到参数1,2,3中的变量值
log.info("菜品批量删除,{}",ids);
dishService.deleteBatch(ids);
return Result.success();
}
Service层接口
在DishService接口中声明deleteBatch方法:
java
//菜品批量删除
void deleteBatch(List<Long> ids);
Service层实现类
在DishServiceImpl中实现deleteBatch方法:
java
//菜品批量删除
@Transactional//事务
public void deleteBatch(List<Long> ids) {
//判断当前菜品是否能够删除---是否存在起售中的菜品
for (Long id : ids) {
//根据主键查询菜品
Dish dish=dishMapper.getById(id);
//查询是否起售
if (Objects.equals(dish.getStatus(), StatusConstant.ENABLE)){
//当前菜品处于起售中,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
}
}
//判断当前菜品是否能够删除---是否被套餐关联了
List<Long> setmealIds=setmealDishMapper.getSetmealIdsByDishIds(ids);
if (setmealIds!=null&& !setmealIds.isEmpty()){
//当前菜品被套餐关联了,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
}
//删除菜品表中的菜品数据
for (Long id : ids) {
dishMapper.deleteById(id);
//删除菜品关联的口味数据
dishFlavorMapper.deleteByDishId(id);
}
Mapper层
在DishMapper中声明getById方法,并配置SQL:
java
//根据主键查询菜品
@Select("select *from dish where id=#{id}")
Dish getById(Long id);
创建SetmealDishMapper,声明getSetmealIdsByDishIds方法,并在xml文件中编写SQL:
java
package com.sky.mapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SetmealDishMapper {
//根据菜品id查询对应的套餐id
List<Long> getSetmealIdsByDishIds(List<Long> dishIds);
}
SetmealDishMapper.xml
java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.SetmealDishMapper">
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
select setmeal_id from setmeal_dish where dish_id in
<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
#{dishId}
</foreach>
</select>
</mapper>
在DishMapper.java中声明deleteById方法并配置SQL:
java
//根据主键删除菜品数据
@Delete("delete from dish where id=#{id}")
void deleteById(Long id);
在DishFlavorMapper中声明deleteByDishId方法并配置SQL:
java
//根据菜品id删除对应的口味数据
@Delete("delete from dish_flavor where dish_id=#{dishId}")
void deleteByDishId(Long dishId);
性能优化
在DishServiceImpl中,删除菜品是一条一条传送执行的,大大降低了执行效率,原代码如下:
java
//删除菜品表中的菜品数据
for (Long id : ids) {
dishMapper.deleteById(id);
//删除菜品关联的口味数据
dishFlavorMapper.deleteByDishId(id);
}
为了提高性能,进行修改,使用动态sql执行删除操作
java
//根据菜品id集合批量删除菜品数据
//sql:delete from dish where id in(?,?,?)
dishMapper.deleteByIds(ids);
//根据菜品id集合批量删除关联的口味数据
//sql:delete from dish_flavor where dish_id in(?,?,?)
dishMapper.deleteByDishIds(ids);
在DishMapper中
java
//根据菜品id集合批量删除菜品
void deleteByIds(List<Long> ids);
//根据菜品id集合批量删除关联的口味数据
void deleteByDishIds(List<Long> dishId);
在DishMapper.xml中
java
<delete id="deleteByIds">
delete from dish where id in
<foreach collection="ids" open="(" separator="," close=")" item="id">
#{id}
</foreach>
</delete>
<delete id="deleteByDishIds">
delete from dish_flavor where dish_id in
<foreach collection="dishIds" open="(" close=")" separator="," item="dishId">
#{dishId}
</foreach>
</delete>
功能测试
进行前后端联调,删除成功
修改菜品
需求分析和设计
接口:
-
根据id查询菜品
-
根据类型查询分类(已实现)
-
文件上传(已实现)
-
修改菜品
代码开发
根据id查询菜品实现
Controller层
根据id查询菜品的接口定义在DishController中创建方法:
java
//根据id查询菜品
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品")
public Result<DishVO> getById(@PathVariable Long id){
log.info("根据id查询菜品:{}",id);
DishVO dishVO=dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}
Service层接口
在DishService接口中声明getByIdWithFlavor方法:
java
//根据id查询菜品和对应的口味数据
DishVO getByIdWithFlavor(Long id);
Service层实现类
在DishServiceImpl中实现getByIdWithFlavor方法:
java
//根据id查询菜品和对应的口味数据
@Override
public DishVO getByIdWithFlavor(Long id) {
//根据id查询菜品数据
Dish dish=dishMapper.getById(id);
//根据菜品id查询口味数据
List<DishFlavor> dishFlavors=dishFlavorMapper.getByDishId(id);
//将查询到的数据封装到VO
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(dish,dishVO);
dishVO.setFlavors(dishFlavors);
return dishVO;
}
Mapper层
在DishFlavorMapper中声明getByDishId方法,并配置SQL:
java
//根据id查询对应的口味数据
@Select("select *from dish_flavor where dish_id=#{dishId}")
List<DishFlavor> getByDishId(Long dishId);
修改菜品实现
Controller层
根据修改菜品的接口定义在DishController中创建方法:
java
//修改菜品
@PutMapping
@ApiOperation("修改菜品")
public Result<String> update(@RequestBody DishDTO dishDTO){
log.info("修改菜品:{}",dishDTO);
dishService.updateWithFlavor(dishDTO);
return Result.success();
}
Service层接口
在DishService接口中声明updateWithFlavor方法:
java
//根据id修改菜品基本信息和对应的口味数据
void updateWithFlavor(DishDTO dishDTO);
Service层实现类
在DishServiceImpl中实现updateWithFlavor方法:
java
//根据id修改菜品基本信息和对应的口味信息
@Override
public void updateWithFlavor(DishDTO dishDTO) {
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO,dish);
//修改菜品表基本信息
dishMapper.update(dish);
//删除原有的口味数据
dishFlavorMapper.deleteByDishId(dishDTO.getId());
//重新插入口味数据
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors!=null&& !flavors.isEmpty()){
flavors.forEach(dishFlavor -> {
dishFlavor.setDishId(dishDTO.getId());
});
//向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}
}
Mapper层
在DishMapper中,声明update方法:
java
//根据id动态修改菜品数据
@AutoFill(value = OperationType.UPDATE)
void update(Dish dish);
并在DishMapper.xml文件中编写SQL:
java
<update id="update">
update dish
<set>
<if test="name!=null">name=#{name},</if>
<if test="categoryId!=null">category_id=#{categoryId},</if>
<if test="price!=null">price=#{price},</if>
<if test="image!=null">image=#{image},</if>
<if test="description!=null">description=#{description},</if>
<if test="status!=null">status=#{status},</if>
<if test="updateTime!=null">update_time=#{updateTime},</if>
<if test="updateUser!=null">update_user=#{updateUser},</if>
</set>
where id=#{id}
</update>