
新增分类
页面逻辑




可以看到有俩种选择,可以新增菜品分类以及套餐分类,但是具体的页面逻辑是类似的,所以我们后端处理的时候用的是同样的逻辑


代码开发
我们先定义了实体类Category类,用type字段区分是菜品分类还是套餐分类,其他的信息是无差别的
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//类型: 1菜品分类 2套餐分类
private Integer type;
//分类名称
private String name;
//顺序
private Integer sort;
//分类状态 0标识禁用 1表示启用
private Integer status;
//创建时间
private LocalDateTime createTime;
//更新时间
private LocalDateTime updateTime;
//创建人
private Long createUser;
//修改人
private Long updateUser;
}
同样的逻辑,DTO对象接收前端数据,再用对象拷贝,用其他类进行后续操作,这里设置创建时间、修改时间、创建人、修改人,我们先前用AOP+注解的形式实现了自动补全这四个字段,所以这里我们不用再额外写,只需要再mapper方法上面加上@AutoFill注解即可
/**
* 新增分类
* @param categoryDTO
*/
public void save(CategoryDTO categoryDTO) {
Category category = new Category();
//属性拷贝
BeanUtils.copyProperties(categoryDTO, category);
//分类状态默认为禁用状态0
category.setStatus(StatusConstant.DISABLE);
//设置创建时间、修改时间、创建人、修改人
// category.setCreateTime(LocalDateTime.now());
// category.setUpdateTime(LocalDateTime.now());
// category.setCreateUser(BaseContext.getCurrentId());
// category.setUpdateUser(BaseContext.getCurrentId());
categoryMapper.insert(category);
}
分类分页查询
类似于员工分页查询

/**
* 分页查询
* @param categoryPageQueryDTO
* @return
*/
public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
PageHelper.startPage(
categoryPageQueryDTO.getPage(),
categoryPageQueryDTO.getPageSize());
//下一条sql进行分页,自动加入limit关键字分页
Page<Category> page = categoryMapper.pageQuery(categoryPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
根据类型查询分类

前面的新增菜品分类,可以有俩种选择,菜品和套餐,这里我们可以根据这俩个类型进行查询操作,我们的类别在前面的Category类中是用的type属性辨别的,这里也是如此

这里我们只看SQL语句,需要确保当前分类是启用的,才有可能被查询到,然后用到了动态SQL
<select id="list" resultType="Category">
select * from category
where status = 1
<if test="type != null">
and type = #{type}
</if>
order by sort asc,create_time desc
</select>
很重要的一点是,前端项目启动的时候都会先发送一次查询当前所有正在发售的分类,前端会将这些数据保留下面,后续进行操作的时候,会用到这些分类,比如说新增一个菜品的时候,我们需要知道当前有哪些分类,在项目启动的时候发送一次这个请求,可以节省后续的多次请求,同时也可以减少查询负担


根据id删除分类

/**
* 根据id删除分类
* @param id
*/
public void deleteById(Long id) {
//查询当前分类是否关联了菜品,如果关联了就抛出业务异常
Integer count = dishMapper.countByCategoryId(id);
if(count > 0){
//当前分类下有菜品,不能删除
throw new DeletionNotAllowedException(
MessageConstant.CATEGORY_BE_RELATED_BY_DISH);
}
//查询当前分类是否关联了套餐,如果关联了就抛出业务异常
count = setmealMapper.countByCategoryId(id);
if(count > 0){
//当前分类下有菜品,不能删除
throw new DeletionNotAllowedException(
MessageConstant.CATEGORY_BE_RELATED_BY_SETMEAL);
}
//删除分类数据
categoryMapper.deleteById(id);
}
这里先检查是否与菜品进行了关联,是否与套餐进行了关联,若有关联则不能删除。我们菜品和套餐在页面中点击新增操作的时候,都必须关联分类,菜品关联菜品分类等,所以这是我们必须要检验后才能进行删除操作的前提。
启用、禁用分类
业务分析
启用和禁用分类,我们需要前端传递一个状态值status,以便于后端直接用这个值进行修改操作,并且我们同时还要前端传递当前操作分类的id,这样我们可以定位这个分类。所以在Path中有status,在Query中有id

代码实现
用相应的方式接收前端传递过来的俩个参数
/**
* 启用、禁用分类
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("启用禁用分类")
public Result<String> startOrStop(@PathVariable("status") Integer status, Long id){
categoryService.startOrStop(status,id);
return Result.success();
}
Service层代码:
前端只传递了状态值以及分类id,我们要做的数据库操作是修改,所以我们还另外需要俩个值,修改人id以及修改时间,将这四个值封装到Category类中,将这个类传递给相应mapper方法进行数据库操作。
这样的操作可以让层间传递数据更加简便,不需要我们在方法上定义很多数据字段
/**
* 启用、禁用分类
* @param status
* @param id
*/
public void startOrStop(Integer status, Long id) {
Category category = Category.builder()
.id(id)
.status(status)
.updateTime(LocalDateTime.now())
.updateUser(BaseContext.getCurrentId())
.build();
categoryMapper.update(category);
}
修改分类
我们注意到路径与之前的一些是相同的,但是方法不同,但是我们依旧可以调用不同的方法。这就是RESTful 规则。总结的说就是同一条 URL 可以表达多种"动作",靠的就是 HTTP 动词(GET/POST/PUT/DELETE...)来区分语义,而不是把动作再写进 URL

前端页面:

代码开发
因为前端穿的数据很多,所以我们依旧使用DTO对象来接收
用一个对象来接收前端参数的时候,会加入这个对象与前端相同名的数据,能对上的就灌,对不上的就忽略"
这个对象可以比前端传递的数据,拥有更多的属性字段,也可以少(但一般不会,会丢失前端传递的数据)
/**
* 修改分类
* @param categoryDTO
*/
public void update(CategoryDTO categoryDTO) {
Category category = new Category();
BeanUtils.copyProperties(categoryDTO,category);
//设置修改时间、修改人
// category.setUpdateTime(LocalDateTime.now());
// category.setUpdateUser(BaseContext.getCurrentId());
categoryMapper.update(category);
}
核心代码就是对象拷贝,用前端传递的数据去修改。