因为day-4属于作业部分,主要是完成套餐的CRUD,这里我就写下自己的思路以及代码
这里先实现新增功能,接口图如下:
(视频里面的接口管理平台已经关闭了,这里是我自己搭建的一个Yapi平台,地址如下,大家可以免费使用YApi Pro-高效、易用、功能强大的可视化接口管理平台)
首先在DishController添加一个根据分类id查询菜品的控制类:
/**
* 根据分类ID查询菜品
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result> list(Long categoryId){
log.info("分类id查询菜品:{}",categoryId);
List list= dishService.getList(categoryId);
return Result.success(list);
}
在DishService写上方法
/**
* 根据分类id查询菜品
* @param categoryId
* @return
*/
List getList(Long categoryId);
在DishServiceImpl实现一下方法:
/**
* 根据分类ID查询菜品
* @param categoryId
* @return
*/
@Override
public List getList(Long categoryId) {
Dish dish= Dish.builder()
.categoryId(categoryId)
.status(StatusConstant.ENABLE)
.build();
return dishMapper.list(dish);
return null;
}
编写Dishmapper.xml,这里我们采用的是动态查询,所以我们使用xml编写,而不是注释,将查询出来的结果根据创建时间进行降序排序:
接下来我们做套餐管理的新增,这里大家可以测试一下查询功能
”------------------------------------------------分割线-----------------------------------------------------------------“
新建一个SetmealController控制类,新建SetmealService和SetmealServiceimpl类,这里我就省略创建步骤了,大家自行创建:
/**
* 套餐管理
*/
@RestController
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐管理相关接口")
@Slf4j
public class SetmealController {
@Autowired
private SetmealService setmealService;
}
编写新增控制方法:
@PostMapping
@ApiOperation("新增套餐")
public Result save(@RequestBody SetmealDTO setmealDTO){
//根据前面老师的思路采用DTO作为对象
log.info("新增菜品信息:{}",setmealDTO);
setmealService.saveWithDish(setmealDTO);
return null;
}
在setmealService类新增方法,然后实现方法,我这里直接省略了service的步骤,直接写实现类的具体代码:
/**
* 新增套餐,同时需要保存套餐和菜品的关联光系
* @param setmealDTO
*/
@Override
public void saveWithDish(SetmealDTO setmealDTO) {
Setmeal setmeal = new Setmeal();
//使用工具类将对象进行拷贝
BeanUtils.copyProperties(setmealDTO,setmeal);
//向套餐插入数据
setmealMapper.insert(setmeal);
//获取生成套餐的id
Long setmealId = setmeal.getId();
List setmealDishes = setmealDTO.getSetmealDishes();
setmealDishes.forEach(setmealDish ->
setmealDish.setSetmealId(setmealId)
);
//保存套餐和菜品的关联关系
setmealDishMapper.insertBatch(setmealDishes);
}
编写SetmealMapper.xml和SetmealDishMapper.xml
insert into setmeal
(category_id, name, price, status, description, image, create_time, update_time, create_user, update_user)
values (#{categoryId}, #{name}, #{price}, #{status}, #{description}, #{image}, #{createTime}, #{updateTime},
#{createUser}, #{updateUser})
insert into setmeal
(category_id, name, price, status, description, image, create_time, update_time, create_user, update_user)
values (#{categoryId}, #{name}, #{price}, #{status}, #{description}, #{image}, #{createTime}, #{updateTime},
#{createUser}, #{updateUser})
测试功能:
”----------------------------------------------------分割线-----------------------------------------------------------------“
接下来我们进行分页查询代码编写,下面是接口设计图:
在控制类编写方法:
/**
* 套餐的分页查询
* @param setmealPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("分页查询套餐")
public Result page(SetmealPageQueryDTO setmealPageQueryDTO){
log.info("套餐的分页查询:{}",setmealPageQueryDTO);
PageResult pageResult= setmealService.pageQuery(setmealPageQueryDTO);
return Result.success(pageResult);
}
编写SetmealServiceImpl实现类:
/**
* 套餐的分页查询
* @param setmealPageQueryDTO
* @return
*/
@Override
public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {
int pageNum = setmealPageQueryDTO.getPage();
int pageSize = setmealPageQueryDTO.getPageSize();
PageHelper.startPage(pageNum, pageSize);
Page page = setmealMapper.pageQuery(setmealPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
return null;
}
编写SetmealMapper.xml文件
测试功能我直接采用前后端联调了:
”--------------------------------------------------------分割线-----------------------------------------------------------“
接下来我们进行删除套餐和批量删除的功能代码编写,接口设计如下:
在SetmealController控制类编写方法:
/**
* 批量删除套餐
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("批量删除套餐")
public Result delete(@RequestParam List ids){
log.info("批量删除套餐",ids);
setmealService.deleteBatch(ids);
return Result.success();
}
在SetmealService和SetmealServiceImpl编写实现方法:
/**
* 批量删除套餐
* @param ids
*/
@Override
@Transactional
public void deleteBatch(List ids) {
ids.forEach(id -> {
Setmeal setmeal = setmealMapper.getById(id);
if(StatusConstant.ENABLE == setmeal.getStatus()){
//起售中的套餐不能删除
throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
}
});
ids.forEach(setmealId -> {
//删除套餐表中的数据
setmealMapper.deleteById(setmealId);
//删除套餐菜品关系表中的数据
setmealDishMapper.deleteBySetmealId(setmealId);
});
此处的删除SQL语句比较简单,我们就采用注解的方式写:
编写SetmealMapper类:
/**
* 根据id查询套餐
* @param id
* @return
*/
@Select("select * from setmeal where id = #{id}")
Setmeal getById(Long id);
/**
* 根据id删除套餐
* @param setmealId
*/
@Delete("delete from setmeal where id = #{id}")
void deleteById(Long setmealId);
编写SetmealDishMapper类:
/**
* 根据id删除套餐和菜品的关联关系
* @param setmealId
*/
@Delete("delete from setmeal_dish where setmeal_id = #{setmealId}")
void deleteBySetmealId(Long setmealId);
测试一下:
“------------------------------------------------分割线-----------------------------------------------------------------”
接下里我们进行修改菜品的代码编写,接口设计图如下,我们修改的话,按照之前的经验,需要在修改的时候回显数据,所以我们需要先定义一个查询方法,查询出套餐信息:
老样子,我们还是先编写控制类的方法,注意,因为我们需要回显数据,所以这里需要编写两个方法,一个用于查询回显数据,一个用于修改套餐信息:
/**
* 根据id查询套餐
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询套餐")
public Result getById(@PathVariable Long id){
log.info("根据ID查询的数据:{}",id);
SetmealVO setmealVO= setmealService.getByIdWithDish(id);
return Result.success(setmealVO);
}
/**
* 修改套餐
* @param setmealDTO
* @return
*/
@PutMapping
@ApiOperation("修改套餐")
public Result update(@RequestBody SetmealDTO setmealDTO){
log.info("修改的菜品信息:{}",setmealDTO);
setmealService.update(setmealDTO);
return Result.success();
}
编写SetmealServiceImpl类,这里修改信息,我们先修改套餐表,对于Setmeal_dish表我们采用先删除,然后再插入来修改:
/**
* 根据id查询套餐和菜品套餐信息
* @param id
* @return
*/
@Override
public SetmealVO getByIdWithDish(Long id) {
Setmeal setmeal = setmealMapper.getById(id);
List setmealDishes = setmealDishMapper.getBySetmealId(id);
SetmealVO setmealVO = new SetmealVO();
BeanUtils.copyProperties(setmeal, setmealVO);
setmealVO.setSetmealDishes(setmealDishes);
return setmealVO;
}
/**
* 修改套餐
* @param setmealDTO
*/
@Transactional
@Override
public void update(SetmealDTO setmealDTO) {
Setmeal setmeal = new Setmeal();
BeanUtils.copyProperties(setmealDTO, setmeal);
//修改套餐表,执行update
setmealMapper.update(setmeal);
//获取套餐id
Long setmealId = setmealDTO.getId();
//2、删除套餐和菜品的关联关系,操作setmeal_dish表,执行delete
setmealDishMapper.deleteBySetmealId(setmealId);
List setmealDishes = setmealDTO.getSetmealDishes();
setmealDishes.forEach(setmealDish -> {
setmealDish.setSetmealId(setmealId);
});
//重新插入套餐和菜品的关联关系,操作setmeal_dish表,执行insert
setmealDishMapper.insertBatch(setmealDishes);
}
编写SetmealDishMapper类的查询方法,很简单的SQL语句我们一律采用注解写:
/**
* 根据id查询套餐和菜品的关联信息
* @param id
* @return
*/
@Select("select * from setmeal_dish where setmeal_id = #{setmealId}")
List getBySetmealId(Long id);
功能测试:
“----------------------------------------------分割线---------------------------------------------------------”
我们进行最后的起售or停售功能测试老规矩,先写控制类,接口设计如下:
编写 SetmealController控制类:
@PostMapping("/status/{status}")
@ApiOperation("套餐起售或者停售接口")
public Result startOrStop (@PathVariable Integer status,Long id){
log.info("起售或停售套餐信息",status,id);
setmealService.startOrStop(status,id);
return Result.success();
}
编写SetmealServiceImpl实现类,原谅我的懒,service类我就没写了:
/**
* 起售或者停售套餐
* @param status
* @param id
*/
@Override
public void startOrStop(Integer status, Long id) {
//因为套餐和菜品又关联关系,所以再启用套餐之前我们先判定一下是否有包含菜品停售,如果有的话就没法启用套餐
if(status == StatusConstant.ENABLE){
//select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = ?
List dishList = dishMapper.getBySetmealId(id);
if(dishList != null && dishList.size() > 0){
dishList.forEach(dish -> {
if(StatusConstant.DISABLE == dish.getStatus()){
throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
}
});
}
}
Setmeal setmeal = Setmeal.builder()
.id(id)
.status(status)
.build();
setmealMapper.update(setmeal);
}
编写DishMapper类查询一下菜品信息看是否有停售:
/**
* 根据套餐id查询菜品
* @param id
* @return
*/
@Select("select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = #{setmealId}")
List getBySetmealId(Long id);
测试:
OK,我们整个套餐管理的模块就全部完成啦!!!