分页查询、删除和修改菜品
1. 菜品分页查询
1.1 需求分析和设计
1.1.1 产品原型
系统中的菜品数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。
菜品分页原型:
在菜品列表展示时,除了菜品的基本信息(名称、售价、售卖状态、最后操作时间)外,还有两个字段略微特殊,第一个是图片字段 ,我们从数据库查询出来的仅仅是图片的名字,图片要想在表格中回显展示出来,就需要下载这个图片。第二个是菜品分类,这里展示的是分类名称,而不是分类ID,此时我们就需要根据菜品的分类ID,去分类表中查询分类信息,然后在页面展示。
业务规则:
- 根据页码展示菜品信息
- 每页展示10条数据
- 分页查询时可以根据需要输入菜品名称、菜品分类、菜品状态进行查询
1.1.2 接口设计
根据上述原型图,设计出相应的接口。
1.2 代码开发
1.2.1 设计DTO类
根据菜品分页查询接口定义设计对应的DTO:
在sky-pojo模块中,已定义
packagecom.sky.dto;@DatapublicclassDishPageQueryDTOimplementsSerializable{privateint page;privateint pageSize;privateString name;privateInteger categoryId;//分类idprivateInteger status;//状态 0表示禁用 1表示启用}
1.2.2 设计VO类
根据菜品分页查询接口定义设计对应的VO:
在sky-pojo模块中,已定义
packagecom.sky.vo;@Data@Builder@NoArgsConstructor@AllArgsConstructorpublicclassDishVOimplementsSerializable{privateLong id;//菜品名称privateString name;//菜品分类idprivateLong categoryId;//菜品价格privateBigDecimal price;//图片privateString image;//描述信息privateString description;//0 停售 1 起售privateInteger status;//更新时间privateLocalDateTime updateTime;//分类名称privateString categoryName;//菜品关联的口味privateList<DishFlavor> flavors =newArrayList<>();}
1.2.3 Controller层
根据接口定义创建DishController的page分页查询方法:
/**
* 菜品分页查询
*
* @param dishPageQueryDTO
* @return
*/@GetMapping("/page")@ApiOperation("菜品分页查询")publicResult<PageResult>page(DishPageQueryDTO dishPageQueryDTO){
log.info("菜品分页查询:{}", dishPageQueryDTO);PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);//后绪步骤定义returnResult.success(pageResult);}
1.2.4 Service层接口
在 DishService 中扩展分页查询方法:
/**
* 菜品分页查询
*
* @param dishPageQueryDTO
* @return
*/PageResultpageQuery(DishPageQueryDTO dishPageQueryDTO);
1.2.5 Service层实现类
在 DishServiceImpl 中实现分页查询方法:
/**
* 菜品分页查询
*
* @param dishPageQueryDTO
* @return
*/publicPageResultpageQuery(DishPageQueryDTO dishPageQueryDTO){PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);//后绪步骤实现returnnewPageResult(page.getTotal(), page.getResult());}
1.2.6 Mapper层
在 DishMapper 接口中声明 pageQuery 方法:
/**
* 菜品分页查询
*
* @param dishPageQueryDTO
* @return
*/Page<DishVO>pageQuery(DishPageQueryDTO dishPageQueryDTO);
在 DishMapper.xml 中编写SQL:
<selectid="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><iftest="name != null">
and d.name like concat('%',#{name},'%')
</if><iftest="categoryId != null">
and d.category_id = #{categoryId}
</if><iftest="status != null">
and d.status = #{status}
</if></where>
order by d.create_time desc
</select>
1.3 功能测试
1.3.2 前后端联调测试
启动nginx,访问 http://localhost
点击菜品管理
数据成功查出。
2. 删除菜品
2.1 需求分析和设计
2.1.1 产品原型
在菜品列表页面,每个菜品后面对应的操作分别为修改、删除、停售,可通过删除功能完成对菜品及相关的数据进行删除。
删除菜品原型:
业务规则:
- 可以一次删除一个菜品,也可以批量删除菜品
- 起售中的菜品不能删除
- 被套餐关联的菜品不能删除
- 删除菜品后,关联的口味数据也需要删除掉
2.1.2 接口设计
根据上述原型图,设计出相应的接口。
注意:删除一个菜品和批量删除菜品共用一个接口,故ids可包含多个菜品id,之间用逗号分隔。
2.1.3 表设计
在进行删除菜品操作时,会涉及到以下三张表。
注意事项:
- 在dish表中删除菜品基本数据时,同时,也要把关联在dish_flavor表中的数据一块删除。
- setmeal_dish表为菜品和套餐关联的中间表。
- 若删除的菜品数据关联着某个套餐,此时,删除失败。
- 若要删除套餐关联的菜品数据,先解除两者关联,再对菜品进行删除。
2.2 代码开发
2.1.2 Controller层
根据删除菜品的接口定义在DishController中创建方法:
/**
* 菜品批量删除
*
* @param ids
* @return
*/@DeleteMapping@ApiOperation("菜品批量删除")publicResultdelete(@RequestParamList<Long> ids){
log.info("菜品批量删除:{}", ids);
dishService.deleteBatch(ids);//后绪步骤实现returnResult.success();}
2.2.2 Service层接口
在DishService接口中声明deleteBatch方法:
/**
* 菜品批量删除
*
* @param ids
*/voiddeleteBatch(List<Long> ids);
2.2.3 Service层实现类
在DishServiceImpl中实现deleteBatch方法:
@AutowiredprivateSetmealDishMapper setmealDishMapper;/**
* 菜品批量删除
*
* @param ids
*/@Transactional//事务publicvoiddeleteBatch(List<Long> ids){//判断当前菜品是否能够删除---是否存在起售中的菜品??for(Long id : ids){Dish dish = dishMapper.getById(id);//后绪步骤实现if(dish.getStatus()==StatusConstant.ENABLE){//当前菜品处于起售中,不能删除thrownewDeletionNotAllowedException(MessageConstant.DISH_ON_SALE);}}//判断当前菜品是否能够删除---是否被套餐关联了??List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);if(setmealIds !=null&& setmealIds.size()>0){//当前菜品被套餐关联了,不能删除thrownewDeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);}//删除菜品表中的菜品数据for(Long id : ids){
dishMapper.deleteById(id);//后绪步骤实现//删除菜品关联的口味数据
dishFlavorMapper.deleteByDishId(id);//后绪步骤实现}}
2.2.4 Mapper层
在DishMapper中声明getById方法,并配置SQL:
/**
* 根据主键查询菜品
*
* @param id
* @return
*/@Select("select * from dish where id = #{id}")DishgetById(Long id);
创建SetmealDishMapper,声明getSetmealIdsByDishIds方法,并在xml文件中编写SQL:
packagecom.sky.mapper;@MapperpublicinterfaceSetmealDishMapper{/**
* 根据菜品id查询对应的套餐id
*
* @param dishIds
* @return
*///select setmeal_id from setmeal_dish where dish_id in (1,2,3,4)List<Long>getSetmealIdsByDishIds(List<Long> dishIds);}
SetmealDishMapper.xml
<mappernamespace="com.sky.mapper.SetmealDishMapper"><selectid="getSetmealIdsByDishIds"resultType="java.lang.Long">
select setmeal_id from setmeal_dish where dish_id in
<foreachcollection="dishIds"item="dishId"separator=","open="("close=")">
#{dishId}
</foreach></select></mapper>
在DishMapper.java中声明deleteById方法并配置SQL:
/**
* 根据主键删除菜品数据
*
* @param id
*/@Delete("delete from dish where id = #{id}")voiddeleteById(Long id);
在DishFlavorMapper中声明deleteByDishId方法并配置SQL:
/**
* 根据菜品id删除对应的口味数据
* @param dishId
*/@Delete("delete from dish_flavor where dish_id = #{dishId}")voiddeleteByDishId(Long dishId);
2.3 功能测试
既可以通过Swagger接口文档进行测试,也可以通过前后端联调测试,接下来,我们直接使用前后端联调测试。
进入到菜品列表查询页面
对测试菜品进行删除操作
同时,进到dish表和dish_flavor两个表查看测试菜品的相关数据都已被成功删除。
再次,删除状态为启售的菜品
点击批量删除
删除失败,因为起售中的菜品不能删除。
3. 修改菜品
3.1 需求分析和设计
3.1.1 产品原型
在菜品管理列表页面点击修改按钮,跳转到修改菜品页面,在修改页面回显菜品相关信息并进行修改,最后点击保存按钮完成修改操作。
修改菜品原型:
3.1.2 接口设计
通过对上述原型图进行分析,该页面共涉及4个接口。
接口:
- 根据id查询菜品
- 根据类型查询分类(已实现)
- 文件上传(已实现)
- 修改菜品
我们只需要实现根据id查询菜品和修改菜品两个接口,接下来,我们来重点分析这两个接口。
1). 根据id查询菜品
2). 修改菜品
注:因为是修改功能,请求方式可设置为PUT。
3.2 代码开发
3.2.1 根据id查询菜品实现
1). Controller层
根据id查询菜品的接口定义在DishController中创建方法:
/**
* 根据id查询菜品
*
* @param id
* @return
*/@GetMapping("/{id}")@ApiOperation("根据id查询菜品")publicResult<DishVO>getById(@PathVariableLong id){
log.info("根据id查询菜品:{}", id);DishVO dishVO = dishService.getByIdWithFlavor(id);//后绪步骤实现returnResult.success(dishVO);}
2). Service层接口
在DishService接口中声明getByIdWithFlavor方法:
/**
* 根据id查询菜品和对应的口味数据
*
* @param id
* @return
*/DishVOgetByIdWithFlavor(Long id);
3). Service层实现类
在DishServiceImpl中实现getByIdWithFlavor方法:
/**
* 根据id查询菜品和对应的口味数据
*
* @param id
* @return
*/publicDishVOgetByIdWithFlavor(Long id){//根据id查询菜品数据Dish dish = dishMapper.getById(id);//根据菜品id查询口味数据List<DishFlavor> dishFlavors = dishFlavorMapper.getByDishId(id);//后绪步骤实现//将查询到的数据封装到VODishVO dishVO =newDishVO();BeanUtils.copyProperties(dish, dishVO);
dishVO.setFlavors(dishFlavors);return dishVO;}
4). Mapper层
在DishFlavorMapper中声明getByDishId方法,并配置SQL:
/**
* 根据菜品id查询对应的口味数据
* @param dishId
* @return
*/@Select("select * from dish_flavor where dish_id = #{dishId}")List<DishFlavor>getByDishId(Long dishId);
3.2.1 修改菜品实现
1). Controller层
根据修改菜品的接口定义在DishController中创建方法:
/**
* 修改菜品
*
* @param dishDTO
* @return
*/@PutMapping@ApiOperation("修改菜品")publicResultupdate(@RequestBodyDishDTO dishDTO){
log.info("修改菜品:{}", dishDTO);
dishService.updateWithFlavor(dishDTO);returnResult.success();}
2). Service层接口
在DishService接口中声明updateWithFlavor方法:
/**
* 根据id修改菜品基本信息和对应的口味信息
*
* @param dishDTO
*/voidupdateWithFlavor(DishDTO dishDTO);
3). Service层实现类
在DishServiceImpl中实现updateWithFlavor方法:
/**
* 根据id修改菜品基本信息和对应的口味信息
*
* @param dishDTO
*/publicvoidupdateWithFlavor(DishDTO dishDTO){Dish dish =newDish();BeanUtils.copyProperties(dishDTO, dish);//修改菜品表基本信息
dishMapper.update(dish);//删除原有的口味数据
dishFlavorMapper.deleteByDishId(dishDTO.getId());//重新插入口味数据List<DishFlavor> flavors = dishDTO.getFlavors();if(flavors !=null&& flavors.size()>0){
flavors.forEach(dishFlavor ->{
dishFlavor.setDishId(dishDTO.getId());});//向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);}}
4). Mapper层
在DishMapper中,声明update方法:
/**
* 根据id动态修改菜品数据
*
* @param dish
*/@AutoFill(value =OperationType.UPDATE)voidupdate(Dish dish);
并在DishMapper.xml文件中编写SQL:
<updateid="update">
update dish
<set><iftest="name != null">name = #{name},</if><iftest="categoryId != null">category_id = #{categoryId},</if><iftest="price != null">price = #{price},</if><iftest="image != null">image = #{image},</if><iftest="description != null">description = #{description},</if><iftest="status != null">status = #{status},</if><iftest="updateTime != null">update_time = #{updateTime},</if><iftest="updateUser != null">update_user = #{updateUser},</if></set>
where id = #{id}
</update>
3.3 功能测试
通过前后端联调测试 ,可使用Debug方式启动项目,观察运行中步骤。
进入菜品列表查询页面,对第一个菜品的价格进行修改
点击修改,回显成功
菜品价格修改后,点击保存
修改成功。
后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹
版权归原作者 失重外太空. 所有, 如有侵权,请联系我们删除。