瑞吉外卖day3
分类管理
公共字段填充
问题分析
代码实现
1.在实体类属性上加入@TableField注解,指定字段填充策略
@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)//插入和更新时填充字段
2.按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值。此类需要实现MetaObjectHandler接口
@Component @Slf4j public class MyMetaObjectHandler implements MetaObjectHandler { /** * 插入字段自动填充 * @param metaObject */ @Override public void insertFill(MetaObject metaObject) { log.info("插入字段自动填充"); metaObject.setValue("updateTime", LocalDateTime.now()); metaObject.setValue("createTime",LocalDateTime.now()); metaObject.setValue("createUser",new Long(1)); metaObject.setValue("updateUser",new Long(1)); } /** * 更新字段自动填充 * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { log.info("更新字段自动填充"); metaObject.setValue("updateTime", LocalDateTime.now()); metaObject.setValue("updateUser",new Long(1)); } }
功能完善
此时在公共字段自动填充时,设置的updateUser和createUSer的值是固定的, 需要改进为动态获取updateUser和createUser的值
客户端每次发送http请求时,对应的服务端都会分配一个线程来处理,在处理过程中涉及到下面类中的方法都属于相同的一个线程:
1.LoginCheckFilter的doFilter方法
2.EmployeeController的update方法
3.MyMetaObjectHandler的updateFill方法
可以使用ThreadLocal来实现动态获取updateUser和createUser的值
ThreadLocal并不是一个Thread,而是Thread的局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
ThreadLocal常用方法:
. public void set(T value)设置当前线程的线程局部变量的值.
public T get()返回当前线程所对应的线程局部变量的值
我们可以在LoginCheckFilter的doFilter方法中获取当前登录用户id,并调用ThreadLocal的set方法来设置当前线程的线程局部变量的值(用户id),然后在MyMetaObjectHandler的updateFill方法中调用ThreadLocal的get方法来获得当前线程所对应的线程局部变量的值(用户id)。
实现步骤
1.编写BaseContext工具类,基于ThreadLocal封装的工具类
** * 功能描述 * 编写BaseContext工具类,基于ThreadLocal封装的工具类 * @author 15599 * @date 2023/05/09 8:40 */ public class BaseContext { private static ThreadLocal<Long> threadLocal = new ThreadLocal<>(); public static void setCurrentId(Long id){ threadLocal.set(id); } public static Long getCurrentId(){ return threadLocal.get(); } }
2.在loginCheckFilter的doFilter方法中调用BaseContext来设置当前登录用户的id
3.在MyMetaObjectHandler的方法中调用BaseContext来获取登录用户的id
新增分类
需求分析
后台系统中可以管理分类信息,分类包括两种类型,分别是菜品分类和套餐分类。当我们在后台系统中添加菜品时需要选择一个菜品分类,当我们在后台系统中添加一个套餐时需要选择一个套餐分类,在移动端也会按照菜品分类和套餐分类来展示对应的菜品和套餐。
代码开发
类和基本结构
- 实体类Category
- Mapper接口CateGoryMApper
- 业务层接口CategoryService
- 业务层接口实现类CategoryServiceImpl
- 控制层CategoryController
代码开发
@PostMapping
public R<String> save(@RequestBody Category category){
log.info("category={}",category);
categoryService.save(category);
return R.success("新增分类成功");
}
分类信息分页查询
@GetMapping("/page") public R<Page> page(int page,int pageSize){ Page<Category> pageInfo = new Page<>(page,pageSize); //条件构造器 LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper(); queryWrapper.orderByAsc(Category::getSort); categoryService.page(pageInfo,queryWrapper); return R.success(pageInfo); }
删除分类
需求分析
在分类管理列表页面,可以对某个分类进行删除操作。需要注意的是当分类关联了菜品或者套餐时,此分类不允许删除
代码实现
在CategoryService实现类中编写remove方法判断分类是否关联菜品或套餐
@Override public void remove(Long id) { LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Dish::getCategoryId,id); int count1 = dishService.count(queryWrapper); if (count1>0){ //关联菜品。抛出异常 throw new CustomException("该菜品分类已经关联菜品,无法删除"); } LambdaQueryWrapper<Setmeal> queryWrapper1 = new LambdaQueryWrapper<>(); queryWrapper1.eq(Setmeal::getCategoryId,id); int count2 = setmealService.count(queryWrapper1); if (count2>0){ //关联套餐 抛出异常 throw new CustomException("该菜品分类已经关联套餐,无法删除"); } super.removeById(id); }
若关联菜品或套餐,则抛出自定义异常CustomException
public class CustomException extends RuntimeException{ public CustomException(String message){ super(message); } }
在全局异常处理器中处理自定义异常
@ExceptionHandler(CustomException.class) public R<String> exceptionHandler(CustomException ex){ log.error(ex.getMessage()); return R.error(ex.getMessage()); }
修改分类
@PutMapping public R<String> update(@RequestBody Category category){ log.info("修改分类信息{}",category); categoryService.updateById(category); return R.success("修改成功");