系统中的菜品数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。
菜品分页原型:
在菜品列表展示时,除了菜品的基本信息(名称、售价、售卖状态、最后操作时间)外,还有两个字段略微特殊,第一个是图片字段 ,我们从数据库查询出来的仅仅是图片的名字,图片要想在表格中回显展示出来,就需要下载这个图片。第二个是菜品分类,这里展示的是分类名称,而不是分类ID,此时我们就需要根据菜品的分类ID,去分类表中查询分类信息,然后在页面展示。
业务规则:
根据上述原型图,设计出相应的接口。
根据菜品分页查询接口定义设计对应的DTO:
在sky-pojo模块中,已定义
package com.sky.dto; @Data public class DishPageQueryDTO implements Serializable { private int page; private int pageSize; private String name; private Integer categoryId; //分类id private Integer status; //状态 0表示禁用 1表示启用 }
根据菜品分页查询接口定义设计对应的VO:
在sky-pojo模块中,已定义
package com.sky.vo; @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 Listflavors = new ArrayList<>(); }
根据接口定义创建DishController的page分页查询方法:
/** * 菜品分页查询 * * @param dishPageQueryDTO * @return */ @GetMapping("/page") @ApiOperation("菜品分页查询") public Resultpage(DishPageQueryDTO dishPageQueryDTO) { log.info("菜品分页查询:{}", dishPageQueryDTO); PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);//后绪步骤定义 return Result.success(pageResult); }
在 DishService 中扩展分页查询方法:
/** * 菜品分页查询 * * @param dishPageQueryDTO * @return */ PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);
在 DishServiceImpl 中实现分页查询方法:
/** * 菜品分页查询 * * @param dishPageQueryDTO * @return */ public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) { PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize()); Pagepage = dishMapper.pageQuery(dishPageQueryDTO);//后绪步骤实现 return new PageResult(page.getTotal(), page.getResult()); }
在 DishMapper 接口中声明 pageQuery 方法:
/** * 菜品分页查询 * * @param dishPageQueryDTO * @return */ PagepageQuery(DishPageQueryDTO dishPageQueryDTO);
在 DishMapper.xml 中编写SQL:
启动nginx,访问 http://localhost
点击菜品管理
数据成功查出。
在菜品列表页面,每个菜品后面对应的操作分别为修改、删除、停售,可通过删除功能完成对菜品及相关的数据进行删除。
删除菜品原型:
业务规则:
根据上述原型图,设计出相应的接口。
注意:删除一个菜品和批量删除菜品共用一个接口,故ids可包含多个菜品id,之间用逗号分隔。
在进行删除菜品操作时,会涉及到以下三张表。
注意事项:
根据删除菜品的接口定义在DishController中创建方法:
/** * 菜品批量删除 * * @param ids * @return */ @DeleteMapping @ApiOperation("菜品批量删除") public Result delete(@RequestParam Listids) { log.info("菜品批量删除:{}", ids); dishService.deleteBatch(ids);//后绪步骤实现 return Result.success(); }
在DishService接口中声明deleteBatch方法:
/** * 菜品批量删除 * * @param ids */ void deleteBatch(Listids);
在DishServiceImpl中实现deleteBatch方法:
@Autowired private SetmealDishMapper setmealDishMapper; /** * 菜品批量删除 * * @param ids */ @Transactional//事务 public void deleteBatch(Listids) { //判断当前菜品是否能够删除---是否存在起售中的菜品?? for (Long id : ids) { Dish dish = dishMapper.getById(id);//后绪步骤实现 if (dish.getStatus() == StatusConstant.ENABLE) { //当前菜品处于起售中,不能删除 throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE); } } //判断当前菜品是否能够删除---是否被套餐关联了?? List setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids); if (setmealIds != null && setmealIds.size() > 0) { //当前菜品被套餐关联了,不能删除 throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL); } //删除菜品表中的菜品数据 for (Long id : ids) { dishMapper.deleteById(id);//后绪步骤实现 //删除菜品关联的口味数据 dishFlavorMapper.deleteByDishId(id);//后绪步骤实现 } }
在DishMapper中声明getById方法,并配置SQL:
/** * 根据主键查询菜品 * * @param id * @return */ @Select("select * from dish where id = #{id}") Dish getById(Long id);
创建SetmealDishMapper,声明getSetmealIdsByDishIds方法,并在xml文件中编写SQL:
package com.sky.mapper; @Mapper public interface SetmealDishMapper { /** * 根据菜品id查询对应的套餐id * * @param dishIds * @return */ //select setmeal_id from setmeal_dish where dish_id in (1,2,3,4) ListgetSetmealIdsByDishIds(List dishIds); }
SetmealDishMapper.xml
在DishMapper.java中声明deleteById方法并配置SQL:
/** * 根据主键删除菜品数据 * * @param id */ @Delete("delete from dish where id = #{id}") void deleteById(Long id);
在DishFlavorMapper中声明deleteByDishId方法并配置SQL:
/** * 根据菜品id删除对应的口味数据 * @param dishId */ @Delete("delete from dish_flavor where dish_id = #{dishId}") void deleteByDishId(Long dishId);
既可以通过Swagger接口文档进行测试,也可以通过前后端联调测试,接下来,我们直接使用前后端联调测试。
进入到菜品列表查询页面
对测试菜品进行删除操作
同时,进到dish表和dish_flavor两个表查看测试菜品的相关数据都已被成功删除。
再次,删除状态为启售的菜品
点击批量删除
删除失败,因为起售中的菜品不能删除。
在菜品管理列表页面点击修改按钮,跳转到修改菜品页面,在修改页面回显菜品相关信息并进行修改,最后点击保存按钮完成修改操作。
修改菜品原型:
通过对上述原型图进行分析,该页面共涉及4个接口。
接口:
我们只需要实现根据id查询菜品和修改菜品两个接口,接下来,我们来重点分析这两个接口。
1). 根据id查询菜品
2). 修改菜品
注:因为是修改功能,请求方式可设置为PUT。
1). Controller层
根据id查询菜品的接口定义在DishController中创建方法:
/** * 根据id查询菜品 * * @param id * @return */ @GetMapping("/{id}") @ApiOperation("根据id查询菜品") public ResultgetById(@PathVariable Long id) { log.info("根据id查询菜品:{}", id); DishVO dishVO = dishService.getByIdWithFlavor(id);//后绪步骤实现 return Result.success(dishVO); }
2). Service层接口
在DishService接口中声明getByIdWithFlavor方法:
/** * 根据id查询菜品和对应的口味数据 * * @param id * @return */ DishVO getByIdWithFlavor(Long id);
3). Service层实现类
在DishServiceImpl中实现getByIdWithFlavor方法:
/** * 根据id查询菜品和对应的口味数据 * * @param id * @return */ public DishVO getByIdWithFlavor(Long id) { //根据id查询菜品数据 Dish dish = dishMapper.getById(id); //根据菜品id查询口味数据 ListdishFlavors = dishFlavorMapper.getByDishId(id);//后绪步骤实现 //将查询到的数据封装到VO DishVO dishVO = new DishVO(); 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}") ListgetByDishId(Long dishId);
1). Controller层
根据修改菜品的接口定义在DishController中创建方法:
/** * 修改菜品 * * @param dishDTO * @return */ @PutMapping @ApiOperation("修改菜品") public Result update(@RequestBody DishDTO dishDTO) { log.info("修改菜品:{}", dishDTO); dishService.updateWithFlavor(dishDTO); return Result.success(); }
2). Service层接口
在DishService接口中声明updateWithFlavor方法:
/** * 根据id修改菜品基本信息和对应的口味信息 * * @param dishDTO */ void updateWithFlavor(DishDTO dishDTO);
3). Service层实现类
在DishServiceImpl中实现updateWithFlavor方法:
/** * 根据id修改菜品基本信息和对应的口味信息 * * @param dishDTO */ public void updateWithFlavor(DishDTO dishDTO) { Dish dish = new Dish(); BeanUtils.copyProperties(dishDTO, dish); //修改菜品表基本信息 dishMapper.update(dish); //删除原有的口味数据 dishFlavorMapper.deleteByDishId(dishDTO.getId()); //重新插入口味数据 Listflavors = 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) void update(Dish dish);
并在DishMapper.xml文件中编写SQL:
update dish where id = #{id} name = #{name}, category_id = #{categoryId}, price = #{price}, image = #{image}, description = #{description}, status = #{status}, update_time = #{updateTime}, update_user = #{updateUser},
通过前后端联调测试 ,可使用Debug方式启动项目,观察运行中步骤。
进入菜品列表查询页面,对第一个菜品的价格进行修改
点击修改,回显成功
菜品价格修改后,点击保存
修改成功。
后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹
上一篇:spring6概述