苍穹外卖day3(2) 菜品管理(查、删、改、起售停售)


前言

此部分主要包括菜品分页查询,批量删除菜品以及修改菜品。本质上都是一些增删改查,只是要分析清楚业务规则,不同于员工操作,菜品可能关联了口味或者套餐,通常就涉及多表操作。例如:在删除菜品的时候,也要把对应的口味表中信息删除,而起售中的菜品、被套餐关联的菜品不能删除 ;在修改菜品的时候,可能也要修改相应的口味表中的信息…


一、菜品分页查询

菜品信息分页展示在前端界面中

1、接口设计

根据接口定义设计对应的DTO
在这里插入图片描述
根据接口定义设计对应的VO
在这里插入图片描述

2、代码开发

1、DishController定义page分页查询方法

    @GetMapping("/page")
    @ApiOperation("菜品分页查询")
    public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){
        log.info("菜品分页查询:{}",dishPageQueryDTO);
        PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
        return Result.success(pageResult);
    }

2、在DishService接口扩展分页查询方法,在 DishServiceImpl 中实现方法

   @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());
    }

3、在 DishMapper 接口中声明 pageQuery 方法,并在在 DishMapper.xml 中编写SQL语句(多表联查)

<select id="pageQuery" resultType="com.sky.vo.DishVO">
<!--因为dish表中和category表中都有name属性,要为其中一个表中的name取别名-->
        select d.*,c.`name` as categoryName from sky_take_out.dish d left outer JOIN sky_take_out.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>

二、删除菜品

1、业务规则

  • 可以一次删除一个菜品,也可以批量删除菜品
  • 起售中的菜品不能删除
  • 被套餐关联的菜品不能删除
  • 删除菜品后,关联的口味数据也需要删除掉

2、接口设计

在这里插入图片描述

3、数据库设计

根据业务规则可知,这里关联了三张表格。
在这里插入图片描述

4、代码开发

1、根据删除菜品的接口定义在DishController中创建方法

    @DeleteMapping
    @ApiOperation("菜品批量删除")
    public Result delete(@RequestParam List<Long> ids){
        log.info("菜品批量删除:{}",ids);
        dishService.deleteBatch(ids);
        return Result.success();
    }

2、在DishService接口中声明deleteBatch方法,在DishServiceImpl中实现deleteBatch方法

 @Transactional  //涉及多表操作,开启事务管理,确保方法的原子性
    public void deleteBatch(List<Long> ids) {
        //1、判断当前菜品是否能够删除--是否存在起售中的菜品  status
        for (Long id : ids) {
            //根据菜品id查询这个菜品所有信息,返回一个dish对象
            Dish dish = dishMapper.getById(id);
            if(dish.getStatus() == StatusConstant.ENABLE){
                //当前菜品处于起售中,不能删除
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }
        //2、判断当前菜品是否能够删除--根据菜品id查询是否被套餐关联了
        List<Long> setmealIds = setmealDishMapper.getSetmealIdByDishIds(ids);
        if(setmealIds != null && setmealIds.size() > 0){
            //当前菜品被套餐关联,不能删除
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        //3、删除菜品表中的菜品数据
       /* for (Long id : ids) {
            dishMapper.deleteById(id);
            //删除菜品关联的口味数据
            dishFlavorMapper.deleteByDishId(id);
        } */
        //批量删除
        //delete from dish where id in {?,?,?}
        //根据菜品id集合批量删除菜品数据
        dishMapper.deleteByIds(ids);
        //delete from dish_flavor where id in {?,?,?}
        //根据菜品id集合批量删除关联的口味数据
        dishFlavorMapper.deleteByDishIds(ids);
    }

3、在DishMapper中声明getById方法,并配置Sql语句

@Select("select * from sky_take_out.dish where id = #{id}")
    Dish getById(Long id);

4、在SetmealDishMapper声明getSetmealIdsByDishIds方法,并在SetmealDishMapper.xml文件中编写SQL

<select id="getSetmealIdByDishIds" resultType="java.lang.Long">
		select setmeal_id from sky_take_out.setmeal_dish where dish_id in
        <foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
            #{dishId}
        </foreach>
</select>

5、在DishMapper.xml中声明deleteById方法并配置SQL

@Delete("delete from dish where id = #{id}")
void deleteById(Long id);

6、在DishFlavorMapper中声明deleteByDishId方法并配置SQL

@Delete("delete from dish_flavor where dish_id = #{dishId}")
void deleteByDishId(Long dishId);

三、修改菜品

1、接口设计

  • 根据id查询菜品 (菜品信息回显)
  • 根据菜品类型查询分类(已实现)
  • 文件上传(已实现)
  • 修改菜品

1.1 根据id查询菜品

在这里插入图片描述

1.2 修改菜品

在这里插入图片描述

2、代码开发

2.1 根据id查询菜品

查询的信息包括菜品信息和关联的口味数据
1、在Dishcontroller中编写方法

    @GetMapping("/{id}")
    @ApiOperation("根据id查询菜品")
    public Result<DishVO> getById(@PathVariable Long id){
        log.info("根据id查询菜品 {}",id);
        DishVO dishVO = dishService.getByIdWithFlavor(id);
        return Result.success(dishVO);
    }

2、在DishService接口中定义getByIdWithFlavor方法,在DishServiceImpl中实现方法

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;
    }

3、分别在DishMapper定义getById方法(菜品分页查询业务中已定义)和DishFlavorMapper接口中定义getByDishId方法

    @Select("select * from sky_take_out.dish_flavor where dish_id = #{dishId}")
    List<DishFlavor> getByDishId(Long dishId);

2.2 修改菜品

1、在Dishcontroller中编写方法

    @PutMapping
    @ApiOperation("修改菜品")
    public Result update(@RequestBody DishDTO dishDTO){
        log.info("修改菜品 {}",dishDTO);
        dishService.updateWithFlavor(dishDTO);
        return Result.success();
    }

2、在DishService接口中定义gupdateWithFlavor方法,在DishServiceImpl中实现方法

 public void updateWithFlavor(DishDTO dishDTO) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        //1 修改菜品表基本信息
        dishMapper.update(dish);
        //2 先删除原来的口味数据
        dishFlavorMapper.deleteByDishId(dishDTO.getId());
        //3 再插入口味
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if(flavors != null && flavors.size() > 0){
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(dishDTO.getId());
            });
            //向口味表插入n条数据
            dishFlavorMapper.insertBatch(flavors);
        }
    }

3、在dishMapper中定义方法

@AutoFill(OperationType.UPDATE)
void update(Dish dish);

4、在dishMapper.xml中编写sql语句

 <update id="update">
        update sky_take_out.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>

四、菜品起售停售

1、接口设计

菜品起售表示该菜品可以对外售卖,在用户端可以点餐
菜品停售表示此菜品下架,用户端无法点餐
如果执行停售操作,则包含此菜品的套餐也需要停售。(一定要注意这一点)
在这里插入图片描述

2、代码开发

1、在dishController层编写方法

@PostMapping("/status/{status}")
    @ApiOperation("菜品起售停售")
    public Result startOrStop(@PathVariable Integer status,Long id){
        log.info("菜品起售停售:{},{}",status,id);
        dishService.startOrStop(status,id);
        return Result.success();
    }

2、在DishService接口编写方法,在DishServiceImpl类中实现

//update employee set status = ? where id = ?
 public void startOrStop(Integer status, Long id) {
        Dish dish = Dish.builder()
                .status(status)
                .id(id)
                .build();
        dishMapper.update(dish);
        //如果是停售操作,那么菜品所关联的套餐也不能售卖
        if(status == StatusConstant.DISABLE){
            ArrayList<Long> dishIds = new ArrayList<>();
            dishIds.add(id);
            // select setmealId from setmeal_dish where dish_id in (?,?,?)
            List<Long> setmealIds = setmealDishMapper.getSetmealIdByDishIds(dishIds);
            if(setmealIds != null &&setmealIds.size()>0){
                for (Long setmealId :setmealIds) {
                    Setmeal setmeal = Setmeal.builder()
                            .id(setmealId)
                            .status(StatusConstant.DISABLE)
                            .build();
                    setmealMapper.update(setmeal);
                }
            }
        }
    }  

3、调用DishMapper中的update方法(修改菜品中已实现),对菜品内容进行修改,根据id修改status。
4、在SetmealMapper中定义update方法,对改菜品相关联的套餐信息就行修改,然后再SetmealMapper.xml中编写sql语句。

 @AutoFill(OperationType.UPDATE)
    void update(Setmeal setmeal);
 <update id="update">
        update sky_take_out.setmeal
        <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>

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值