瑞吉外卖(3)—菜品分类管理

目录

一、公共字段填充

1.1 问题分析

1.2 代码实现

二、新增分类

2.1 需求分析

2.2 数据模型

2.3 代码开发

三、菜品类的分页

3.1 需求分析

3.2 代码开发

四、删除分类

4.1 需求分析

4.2 代码开发

五、修改分类

5.1 需求分析

5.2 代码开发


一、公共字段填充

1.1 问题分析

1.2 代码实现

把相关的注解加在需要mybatis-plus自动帮我们填充的字段上面
    
    @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;

 然后设置一个处理类:在此类中为公共字段赋值,需要实现接口;

package com.learn.reggie.common;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 自定义元数据对象处理器
 */

@Slf4j
@Component  //注意:这个要记得交给spring容器管理,不然这个功能就没发用。。。。
//那么怎么确定你要添加的功能是不是要交给容器管理呢?就是你直接写了一个工具类或者是功能类,需要对数据库的数据或者是数据库数据的结果产生影响的时候,你明明写了这样一个类,但是功能却没有生效,那么这个时候就要首先考虑是不是容器没有托管这个类
public class MyMetaObjecthandler implements MetaObjectHandler {

    /**
     * 插入操作,自动填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert]...");
        log.info(metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("createUser", new Long(1)); //这里的id是不能直接获取的,所以这里先写死,后面教怎么动态获取员工id
        metaObject.setValue("updateUser", new Long(1));

    }

    /**
     * 更新操作,自动填充
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update]...");
        log.info(metaObject.toString());

        long id = Thread.currentThread().getId();
        log.info("线程id为:{}",id);

        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", new Long(1));
    }
}

 

 什么是ThreadLocal

然后为了动态的获取员工的id,这里我们使用了threadLocal这个局部变量来获取和存储员工id;

创建一个工具类来设置和获取threadLocal中的员工id, 注意:要先把数据设置进threadLocal中,才能获取到

package com.learn.reggie.common;

/**
 * 基于ThreadLocal封装工具类,用户保存和获取当前登录用户的id
 */

public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    /**
     * 设置值
     * @param id
     */
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }

    /**
     * 获取值
     * @return
     */
    public static Long getCurrentId(){
        return threadLocal.get();
    }

}

在前面我们写的LoginCheckFilter这个过滤器中,把这个地方的代码加上添加和保存id的代码

        //4、判断登录状态,如果已登录,则直接放行
        if (request.getSession().getAttribute("employee") != null) {
            log.info("用户已登录,用户id为:{}", request.getSession().getAttribute("employee"));


            //把用户id存储到本地的ThreadLocal
            Long empId = (Long) request.getSession().getAttribute("employee");
            BaseContext.setCurrentId(empId);

            filterChain.doFilter(request, response);
            return;
        }
把处理器中的静态id改为动态获取:
metaObject.setValue("createUser", BaseContext.getCurrentId());
metaObject.setValue("updateUser",BaseContext.getCurrentId());

功能测试

二、新增分类

2.1 需求分析

 

2.2 数据模型

从资料去复制实体Category类到entity包;

数据库中的表结构:

2.3 代码开发

 创建mapper:

package com.learn.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.learn.reggie.entity.Category;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@Mapper
public interface CategoryMapper extends BaseMapper<Category> {
}

创建service:

package com.learn.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.learn.reggie.entity.Category;
import com.learn.reggie.mapper.CategoryMapper;
import com.learn.reggie.service.CategoryService;
import org.springframework.stereotype.Service;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
}
package com.learn.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.learn.reggie.entity.Category;
import com.learn.reggie.mapper.CategoryMapper;
import com.learn.reggie.service.CategoryService;
import org.springframework.stereotype.Service;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
}

编写controller:

我们发现新增菜品分类的请求地址是:http://localhost:8080/category

提交的数据格式为: {name: "湘菜", type: "1", sort: "1"}

    /**
     * 新增套餐分类
     * @param category
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody Category category) {
        log.info("category:{}", category);
        categoryService.save(category);
        return R.success("新增分类成功");
    }

功能测试:登录后,点击添加新增菜品分类,看是否成功,数据库的数据是否变化;

三、菜品类的分页

3.1 需求分析

3.2 代码开发

   /**
     * 分页查询
     *
     * @param page
     * @param pageSize
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize) {
        //分页构造器
        Page<Category> pageInfo = new Page<>(page, pageSize);
        //条件构造器
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        //添加条件排序,根据sort进行排序
        queryWrapper.orderByAsc(Category::getSort);

        //进行分页查询
        categoryService.page(pageInfo,queryWrapper);

        return R.success(pageInfo);
    }

四、删除分类

4.1 需求分析

4.2 代码开发

代码实现: 注意这里的删除功能是不完整的,因为可能需要删除的数据是与其他表关联的,所以删除之前要先判断该条数据是否与其他表中的数据关联;

    /**
     * 根据id来删除分类的数据
     * @param id
     * @return
     */
    @DeleteMapping()
    public R<String> delete(@RequestParam("ids") Long ids){ //注意这里前端传过来的数据是ids
        categoryService.removeById(ids);
        return R.success("分类信息删除成功");
    }

 功能完善

 创建对应的mapper:

package com.learn.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.learn.reggie.entity.Dish;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@Mapper
public interface DishMapper extends BaseMapper<Dish> {
}
package com.learn.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.learn.reggie.entity.Setmeal;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
}

创建service:

package com.learn.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.learn.reggie.dto.DishDto;
import com.learn.reggie.entity.Dish;

/**
 * @author 咕咕猫
 * @version 1.0
 */
public interface DishService extends IService<Dish> {
}
package com.learn.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.learn.reggie.entity.Setmeal;

/**
 * @author 咕咕猫
 * @version 1.0
 */
public interface SetmealService extends IService<Setmeal> {
}
package com.learn.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.learn.reggie.dto.DishDto;
import com.learn.reggie.entity.Dish;
import com.learn.reggie.entity.DishFlavor;
import com.learn.reggie.mapper.DishMapper;
import com.learn.reggie.service.DishFlavorService;
import com.learn.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
}
package com.learn.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.learn.reggie.entity.Setmeal;
import com.learn.reggie.mapper.SetmealMapper;
import com.learn.reggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
}

添加自定义的service方法:(就是我们需要的业务mybatis没有提供,所以就需要自己另外在service创建新的方法,并且在相关的业务中实现)

//在CategoryService中定义自己需要的方法,直接写就行
void remove(Long id);

在CategoryService实现类中重写该方法:
自定义异常类,因为这里需要抛异常了:

package com.learn.reggie.common;

/**
 * 自定义业务异常
 */

public class CustomException extends RuntimeException{

    public CustomException(String message){
        super(message);
    }

}
//然后在外面前面写的GlobalExceptionHandler全局异常捕获器中添加该异常,这样就可以把相关的异常信息显示给前端操作的人员看见
 
/**
     * 处理自定义的异常,为了让前端展示我们的异常信息,这里需要把异常进行全局捕获,然后返回给前端
     * @param exception
     * @return
     */
    @ExceptionHandler(CustomException.class)
    public R<String> exceptionHandle(CustomException exception){
        log.error(exception.getMessage()); 
        //这里拿到的message是业务类抛出的异常信息,我们把它显示到前端
        return R.error(exception.getMessage());
    }
    /**
     * 根据id删除分类,删除之前需要进行判断
     * @param id
     */
    @Override
    public void remove(Long id) {
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据分类id进行查询
        dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
        //注意:这里使用count方法的时候一定要传入条件查询的对象,否则计数会出现问题,计算出来的是全部的数据的条数
        int count1 = dishService.count(dishLambdaQueryWrapper);

        //查询当前分类是否关联了菜品,如果已经关联,直接抛出一个业务异常
        if (count1 > 0){
            //已经关联菜品,直接抛出一个业务异常
            throw new CustomException("当前分类下关联了菜品,不能删除");
        }

        //查询当前分类是否关联了套餐,如果已经关联,直接抛出一个业务异常
        LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据分类id进行查询
        setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
        //注意:这里使用count方法的时候一定要传入条件查询的对象,否则计数会出现问题,计算出来的是全部的数据的条数
        int count2 = setmealService.count(setmealLambdaQueryWrapper);
        if (count2 > 0){
            //已经关联套餐,直接抛出一个业务异常
            throw new CustomException("当前分类下关联了套餐,不能删除");
        }

        //正常删除分类
        super.removeById(id);
    }

然后在controller调用刚刚实现的方法就行:把之前的remove方法给删除就行,重新调用我们自己实现的方法;

    /**
     * 根据id来删除分类的数据
     * @param id
     * @return
     */
    @DeleteMapping
    public R<String> delete(@RequestParam("ids") Long id){ //注意这里前端传过来的数据是ids
 
        categoryService.remove(id);
        return R.success("分类信息删除成功");
 
    }

测试:自己添加测试数据测试就行;记得一定要测试一下删除有相关联的数据,看会不会删除和在前端提示异常信息;

五、修改分类

5.1 需求分析

5.2 代码开发

    /**
     * 根据id修改分类信息
     * @param category
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody Category category){
        log.info("修改分类信息:{}",category);

        categoryService.updateById(category);
        return R.success("修改分类信息成功");
    }

记得在对应的实体类加上公共字段的值设置:前面我们配置了这个,所以这里只需要加注解就行;

    //创建时间
    @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;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值