当前位置: 首页 > 图灵资讯 > 技术篇> 套餐管理业务开发

套餐管理业务开发

来源:图灵教育
时间:2023-06-25 14:02:24

套餐管理业务开发_业务层

1.新增套餐5-21.1需求分析5-2

套餐管理业务开发_数据_02

1.2数据模型5-2

新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表,还需要向setmealdish表插入套餐和菜品关联数据。

所以在新增套餐时,涉及到两个表:

●setmeal套餐表

●setmeal_dish套餐菜品关系表

套餐管理业务开发_数据_03

套餐管理业务开发_数据_04

1.3代码开发5-31.3.1代码开发-准备工作5-3

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

●实体类SetmealDish(直接从课程资料中导入即可,Setmeal实体前面课程中已经导入过了)

●DTOSetmealDto(直接从课程资料中导入即可)

●Mapper接口SetmealDishMapper

●业务层接口SetmealDishService

●业务层实现类SetmealDishServicelmpl

●控制层SetmealController

套餐菜品关系实体类SetmealDish

package com.itheima.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;import com.baomidou.mybatisplus.annotation.TableField;import lombok.Data;import java.io.Serializable;import java.math.BigDecimal;import java.time.LocalDateTime;/** * 套餐菜品关系  5-3 */@Datapublic class SetmealDish implements Serializable {    private static final long serialVersionUID = 1L;    private Long id;    //套餐id    private Long setmealId;    //菜品id    private Long dishId;    //菜品名称 (冗余字段)    private String name;    //菜品原价    private BigDecimal price;    //份数    private Integer copies;    //排序    private Integer sort;    @TableField(fill = FieldFill.INSERT)    private LocalDateTime createTime;    @TableField(fill = FieldFill.INSERT_UPDATE)    private LocalDateTime updateTime;    @TableField(fill = FieldFill.INSERT)    private Long createUser;    @TableField(fill = FieldFill.INSERT_UPDATE)    private Long updateUser;    //是否删除    private Integer isDeleted;}

数据传输对象DTOSetmealDto

package com.itheima.reggie.dto;import com.itheima.reggie.entity.Setmeal;import com.itheima.reggie.entity.SetmealDish;import lombok.Data;import java.util.List;//数据传输对象DTO  5-3@Datapublic class SetmealDto extends Setmeal {    private List<SetmealDish> setmealDishes;    private String categoryName;}

套餐管理持久层接口SetmealDishMapper

package com.itheima.reggie.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.itheima.reggie.entity.SetmealDish;import org.apache.ibatis.annotations.Mapper;//套餐管理持久层接口  5-3@Mapperpublic interface SetmealDishMapper extends BaseMapper<SetmealDish> {}

套餐管理业务层接口SetmealDishService

package com.itheima.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;import com.itheima.reggie.entity.SetmealDish;//套餐管理业务层接口  5-3public interface SetmealDishService extends IService<SetmealDish> {}

套餐管理业务层接口实现类SetmealDishServiceImpl

package com.itheima.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.itheima.reggie.entity.SetmealDish;import com.itheima.reggie.mapper.SetmealDishMapper;import com.itheima.reggie.service.SetmealDishService;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;//套餐管理业务层接口实现类  5-3@Service@Slf4jpublic class SetmealDishServiceImpl extends ServiceImpl<SetmealDishMapper,SetmealDish> implements SetmealDishService {}

套餐管理控制层SetmealController

package com.itheima.reggie.controller;import com.itheima.reggie.service.SetmealDishService;import com.itheima.reggie.service.SetmealService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;//套餐管理控制层  5-3@RestController@RequestMapping("/setmeal")@Slf4jpublic class SetmealController {    @Autowired    private SetmealService setmealService;    @Autowired    private SetmealDishService setmealDishService;}

1.3.2业务开发

在开发代码之前,需要梳理一下新增套餐时前端页面和服务端的交互过程:

1、页面(backend/page/combo/add.html)发送ajax请求,请求服务端获取套餐分类数据并展示到下拉框中

2、页面发送ajax请求,请求服务端获取菜品分类数据并展示到添加菜品窗口中

3、页面发送ajax请求,请求服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中

4、页面发送请求进行图片上传,请求服务端将图片保存到服务器

5、页面发送请求进行图片下载,将上传的图片进行回显

6、点击保存按钮,发送ajax请求,将套餐相关数据以json形式提交到服务端

开发新增套餐功能,其实就是在服务端编写代码去处理前端页面发送的这6次请求即可。

根据菜品分类的id查询菜品5-4

套餐管理业务开发_List_05

套餐管理业务开发_数据_06

菜品管理DishController

 //根据菜品分类的id查询菜品  5-4    @GetMapping("/list")    public R<List<Dish>> list(Dish dish){        //构造查询条件对象        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());        //添加条件,查询状态为1的也就是起售的菜品        queryWrapper.eq(Dish::getStatus,1);        //添加排序条件        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);        List<Dish> list = dishService.list(queryWrapper);        return R.success(list);    }

套餐管理业务开发_业务层_07

新增套餐业务开发5-55-6

套餐管理业务开发_List_08

套餐管理业务开发_数据_09

注意setmealId没有赋值所以代码中我们需要手动赋值

套餐管理业务开发_业务层_10

套餐管理业务层接口SetmealService

/**     * 新增套餐,同时需要保存套餐和菜品的关联关系   5-6     * @param setmealDto     */    public void saveWithDish(SetmealDto setmealDto);

套餐管理业务层接口实现类SetmealServiceImpl

@Autowired    private SetmealDishService setmealDishService;    //新增套餐,同时需要保存套餐和菜品的关联关系   5-6    @Override    @Transactional //事务    public void saveWithDish(SetmealDto setmealDto) {        //保存套餐的基本信息,操作setmeal,执行insert操作        this.save(setmealDto);        //保存套餐和菜品的关联信息,操作setmeal_dish,执行insert操作        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();        //因为通过debug看到套餐id  setmealId没有赋值,所以我们需要手动添加        setmealDishes = setmealDishes.stream().map((item)->{            item.setSetmealId(setmealDto.getId());            return item;        }).collect(Collectors.toList());        setmealDishService.saveBatch(setmealDishes);    }

套餐管理控制层SetmealController

 //新增套餐  5-5  5-6    @PostMapping    public R<String> save(@RequestBody SetmealDto setmealDto){        log.info("套餐信息 {}",setmealDto);        setmealService.saveWithDish(setmealDto);        return R.success("新增套餐成功");    }

测试成功

套餐管理业务开发_List_11

套餐管理业务开发_数据_12

套餐管理业务开发_List_13

2.套餐信息的分页查询5-82.1需求分析5-8

套餐管理业务开发_业务层_14

2.2代码开发-梳理交互过程5-8

在开发代码之前,需要梳理一下套餐分页查询时前端页面和服务端的交互过程:

1、页面(backend/page/combo/list.html)发送ajax请求,将分页查询参数(page、pageSize、

name)提交到服务端,获取分页数据

2、页面发送请求,请求服务端进行图片下载,用于页面图片展示

开发套餐信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

2.3代码开发5-9

套餐管理业务开发_List_15

套餐管理业务开发_List_16

依然存在和菜品分页查询一样的问题,解决方法也是一样的

套餐管理业务开发_数据_17

套餐管理业务开发_业务层_18

套餐管理控制层SetmealController

//方便我们做套餐分页查询时使用  5-9    @Autowired    private CategoryService categoryService;

套餐管理控制层SetmealController

//套餐信息分页查询  5-9    @GetMapping("/page")    public R<Page> page(int page,int pageSize,String name){        //分页构造器        Page<Setmeal> pageInfo = new Page<>();        Page<SetmealDto> setmealDtoPage = new Page<>();        //添加查询条件        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();        //添加查询条件 根据名字进行like模糊查询        queryWrapper.like(name!=null,Setmeal::getName,name);        //添加排序条件,根据更新时间降序排列        queryWrapper.orderByDesc(Setmeal::getUpdateTime);        //执行分页查询        //这条语句会将我们查询到的数据进行封装 全部封装进Page的对象pageInfo        setmealService.page(pageInfo,queryWrapper);        //此时这个情况和菜品的分页查询一样的原因,我们这里套餐分类的名字显示不出来因为        // 我们传的是id,而前端需要的是name 解决办法和菜品的分页查询一样        //拷贝pageInfo给setmealDtoPage,但是不拷贝records,因为pageInfo对应的泛型是Setmeal        //而我们需要的是SetmealDto        //这个拷贝也只是拷贝page对象的普通属性不包括records属性集合        BeanUtils.copyProperties(pageInfo,setmealDtoPage,"records");        List<Setmeal> records = pageInfo.getRecords();        List<SetmealDto> list = records.stream().map((item)->{            //这个setmealDto是我们新new出来的,里面的属性都是空的,需要我们给赋值            SetmealDto setmealDto = new SetmealDto();            //将Setmeal的普通属性拷贝给setmealDto            BeanUtils.copyProperties(item,setmealDto);            //得到套餐分类id            Long categoryId = item.getCategoryId();            //根据套餐分类id查询出分类对象            Category category = categoryService.getById(categoryId);            if(category!=null){                //得到套餐分类的名称                String categoryName = category.getName();                //将分类名赋值给setmealDto对象                setmealDto.setCategoryName(categoryName);            }            return setmealDto;        }).collect(Collectors.toList());//将这些setmealDto对象收集起来封装成集合        //经过上面一番操作我们就得到了带有 套餐分类名称 的 泛型为setmealDto 的集合        setmealDtoPage.setRecords(list);//给setmealDtoPage的records赋值                return R.success(setmealDtoPage);    }

3.删除套餐5-103.1业务需求5-10

套餐管理业务开发_业务层_19

3.2代码开发-梳理交互过程5-10

套餐管理业务开发_数据_20

3.3代码开发5-11

删除单个套餐

套餐管理业务开发_业务层_21

套餐管理业务开发_List_22

删除多个套餐

套餐管理业务开发_List_23

套餐管理业务层接口SetmealService

 /**     * 删除套餐,同时需要删除套餐和菜品的关联数据   5-11     * @param ids     */    public void removeWithDish(List<Long> ids);

套餐管理业务层接口实现类SetmealServiceImpl

/**     * 删除套餐,同时需要删除套餐和菜品的关联数据  5-11     * @param ids     */    @Transactional    public void removeWithDish(List<Long> ids) {                //查询套餐状态,确定是否可用删除        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper();        //select count(*) from setmeal where id in (1,2,3) and status = 1        queryWrapper.in(Setmeal::getId,ids);        queryWrapper.eq(Setmeal::getStatus,1);        //这里的思想是根据id和status查询,如果查询出来的数据大于0,就证明处于售卖状态,否则为停售状态        int count = this.count(queryWrapper);        if(count > 0){            //如果不能删除,抛出一个业务异常            throw new CustomException("套餐正在售卖中,不能删除");        }        //如果可以删除,先删除套餐表中的数据---setmeal        this.removeByIds(ids);                LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();                //delete from setmeal_dish where setmeal_id in (1,2,3)        lambdaQueryWrapper.in(SetmealDish::getSetmealId,ids);        //删除关系表中的数据----setmeal_dish        setmealDishService.remove(lambdaQueryWrapper);    }

套餐管理控制层SetmealController

/**     * 删除套餐     * @param ids     * @return     */    @DeleteMapping    public R<String> delete(@RequestParam List<Long> ids){        log.info("ids:{}",ids);        setmealService.removeWithDish(ids);        return R.success("套餐数据删除成功");    }

测试

套餐管理业务开发_List_24

套餐管理业务开发_业务层_25

套餐管理业务开发_List_26

4.拓展,修改套餐自己实现代码在reggie_take_out5_1中

分两步实现

4.1首先是将数据回显

这个和菜品修改原理一模一样

套餐管理业务开发_数据_27

套餐管理业务层接口SetmealService

//根据套餐id来查询菜品信息和口味信息   自己实现    public SetmealDto getByIdWithDish(Long id);

套餐管理业务层接口实现类SetmealServiceImpl

//根据套餐id查询套餐数据和对应的菜品   回显数据   自己实现    @Override    public SetmealDto getByIdWithDish(Long id) {        //因为没有SetmealDto这张表,所以我们分两张表查询,一个是Setmeal表一个是SetmealDish表        //首先查询Setmeal表,查到套餐的基本数据不包括套餐对应的菜品        Setmeal setmeal = this.getById(id);        //new一个SetmealDto出来因为我们最终要返回的是SetmealDto因为它里面包括了套餐        // 的基本数据还有对应的菜品        //我们刚new出来的SetmealDto是空的,所以需要将查询到的数据设置进去        SetmealDto setmealDto = new SetmealDto();        BeanUtils.copyProperties(setmeal,setmealDto);        //接着查询套餐菜品关系表,查出对应的菜品        //因为我们的参数id数套餐的id不是套餐菜品关系表的id,所以自己构造查询条件        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();        //使用套餐表id查询套餐菜品关系表        queryWrapper.eq(SetmealDish::getSetmealId,id);        List<SetmealDish> list = setmealDishService.list(queryWrapper);//查出来肯定是集合        //将查出来的对应菜品放进setmealDto        setmealDto.setSetmealDishes(list);        return setmealDto;    }

SetmealController

//修改套餐 之回显数据     自己实现的    //根据套餐id来查询套餐信息和菜品信息    @GetMapping("/{id}")    public R<SetmealDto> get(@PathVariable Long id){        //调用我们自己实现的方法,因为修改套餐涉及两张表        SetmealDto setmealDto = setmealService.getByIdWithDish(id);        return R.success(setmealDto);    }

4.2保存修改

这个也是和修改菜品原理一样

套餐管理业务开发_List_28

套餐管理业务开发_List_29

套餐管理业务层接口SetmealService

//更新套餐信息 同时更新菜品信息 自己实现    public void updateWithDish(SetmealDto setmealDto);

套餐管理业务层接口实现类SetmealServiceImpl

//更新套餐信息同时更新对应菜品   自己实现    @Override    @Transactional    public void updateWithDish(SetmealDto setmealDto) {        //还是一样分两张表来做        //首先更新套餐表        this.updateById(setmealDto);        //更新套餐菜品关系表        //这里我们直接根据套餐id删除原来的菜品,在添加即可        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.eq(SetmealDish::getSetmealId,setmealDto.getId());        setmealDishService.remove(queryWrapper);        //往餐菜品关系表添加新数据        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();        //这里和添加一样的问题  继续为餐菜品关系表添加套餐id        setmealDishes = setmealDishes.stream().map((item)->{            item.setSetmealId(setmealDto.getId());            return item;        }).collect(Collectors.toList());        setmealDishService.saveBatch(setmealDishes);    }

SetmealController

//更新套餐信息 自己实现    @PutMapping    public R<String> update(@RequestBody SetmealDto setmealDto){        //调用我们自己实现的方法,因为修改套餐涉及两张表        setmealService.updateWithDish(setmealDto);        return R.success("套餐修改成功");    }

5.拓展停售起售状态修改自己实现代码在reggie_take_out5_1

停售

套餐管理业务开发_数据_30

套餐管理业务开发_业务层_31

起售

套餐管理业务开发_数据_32

套餐管理业务开发_业务层_33

批量停售

套餐管理业务开发_业务层_34

套餐管理业务开发_业务层_35

批量起售

套餐管理业务开发_数据_36

套餐管理业务开发_List_37

由上图可以这四种功能的请求路径都是一样的,且均使用了restful风格

套餐管理业务层接口SetmealService

 //批量停售起售  自己实现    public void stop(int status,List<Long> ids);

套餐管理业务层接口实现类SetmealServiceImpl

 @Autowired    private SetmealService setmealService;    //批量停售起售  自己实现    @Override    public void stop(int status,List<Long> ids) {        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.in(Setmeal::getId,ids);//先构造id(可能一个也可能多个,因为我们单独停售起售和批量写一起了)        //在构造售卖状态        Setmeal setmeal = new Setmeal();        setmeal.setStatus(status);        setmealService.update(setmeal,queryWrapper);    }

SetmealController

//套餐的起售停售 批量停售 批量起售   自己实现    @PostMapping("/status/{status}")    public R<String> update(@PathVariable int status,@RequestParam List<Long> ids){        //调用我们的方法        setmealService.stop(status,ids);        return R.success("套餐售卖修改成功");    }

测试成功

套餐管理业务开发_业务层_38

套餐管理业务开发_数据_39