这是第二章 没有看过的可以点超链接跳转第一篇
分页查询
由页面得知请求方法是Get请求 请求路径是page 参数是 page和pageSize
页面上边有一个查询按钮 得知 还有一个参数name
我们使用Mybatis-Plus给我们的分页查询Page
@GetMapping("page")
public R page(int page,int pageSize,String name){
//分页构造器
Page pageInfo = new Page(page,pageSize);
//条件构造器
LambdaQueryWrapper queryWrapper=new LambdaQueryWrapper<>();
//这里使用模糊查询**like** 使用等值查询eq需要把所有都打出来
queryWrapper.like(!StringUtils.isEmpty(name),Employee::getName,name);
//根据修改时间降序排列
queryWrapper.orderByDesc(Employee::getUpdateTime);
//执行查询
employeeService.page(pageInfo,queryWrapper);
return R.success(pageInfo);
}
还需要一个MP提供的分页插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
//里边是DbType.MYSQL自己的数据库 我的是Mysql
}
}
修改员工信息 修改status字段
根据id修改状态
@PutMapping //本来只是更新status字段 这个把员工所有都更新了 public Rupdate(@RequestBody Employee employee,HttpSession session){ Long id = (Long) session.getAttribute("employee"); employee.setUpdateTime(LocalDateTime.now()); employee.setUpdateUser(id); employeeService.updateById(employee); return R.success("成功"); }
当我们点击禁用按钮时 前端返回我们的用户id和我们传的id不一致 js对Long型的数字只能精确到前16位 而我们传递过去的数字有19位 我们可以将服务端响应的json进行处理,将Long型的数据统一转换为String
实现步骤 提供消息转换器JacksonObjectMapper 再WebMvc中扩展extendMessageConverters
@Override protected void extendMessageConverters(List> converters) { log.info("消息转换器"); //创建一个新的消息转换器 MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); //设置对象转换器 底层使用jackson将java转换为json converter.setObjectMapper(new JacksonObjectMapper()); //将上面的消息转换器追加到mvc框架的转换器中 index是把我们自己的转换器放到最前边 优先使用 converters.add(0, converter); }
这是springMVC的8个消息转换器
编辑员工
请求路径是restful风格
@GetMapping("/{id}")
public R getByid(@PathVariable Long id){
Employee byId = employeeService.getById(id);
if (byId!=null){
return R.success(byId);
}
return R.error("出现了错误");
}
优化
create_time update_time create_user update_user
这四个公共字段 每次创建或者修改的时候都需要我们去设置 又没有方法让他自己填充呢
答:当然有了 MP给我们封装了自动填充 只需要在字段上加上
@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;
在创建的时候或者更新的时候加上这个注解**@TableField** 表字段 自动填充的策略
我们编写一个类并实现MetaObjectHandler
//当第一次创建时
@Override
public void insertFill(MetaObject metaObject) {
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("createUser",BaseContext.getThreadLocal());
metaObject.setValue("updateUser",BaseContext.getThreadLocal());
metaObject.setValue("updateTime",LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
metaObject.setValue("updateUser",BaseContext.getThreadLocal());
metaObject.setValue("updateTime",LocalDateTime.now());
}
当我们创建和修改时 都需要让他自动设置。还有一个问题 我们知道 像createUser updateUser是从id中获取 那id怎么来呢 聪明的小伙伴说从session中获取 我们没有办法从MetaObjectHandler获取session对象 所以使用ThreadLocal
ThreadLocal不是Thread 而是它的一个局部变量 当使用ThreadLocal维护变量时 都会为该线程提供独立的变量副本 而不会影响其他线程所对应的副本
我们可以在过滤器中拿到id 并使用ThreadLocal的set方法设置当前的用户id,然后再updateUser调用get方法获取
我们先创建一个ThreadLocal封装工具类
//基于ThreadLocal封装工具了 保存获取用户id
public class BaseContext {
private static ThreadLocal threadLocal=new ThreadLocal<>();
public static void setThreadLocal(Long id) {
threadLocal.set(id);
}
public static Long getThreadLocal() {
return threadLocal.get();
}
然后再Filter中设置
Long employee = (Long) request.getSession().getAttribute("employee");
BaseContext.setThreadLocal(employee);
把从session中获取的id放入设置好的ThreadLocal中
然后从MyMetaObjectHandler中调用BaseContext.getThreadLocal()获取
========================================================
第二大模块 新增分类 Category 使用MybatisX创建 实体类 Category Mapper、CategoryService、CategoryServiceImpl、 CategoryController
由前端得知 类型是json类型 请求方式post 请求路径没有
@PostMapping
public R save(@RequestBody Category category) {
categoryService.save(category);
return R.success("成功");
}
Category的分页查询
上边我们写了一个分页查询
@GetMapping("page")
public R page(int page,int pageSize){
//分页构造器
Page pageInfo = new Page<>(page, pageSize);
//构造条件
LambdaQueryWrapper queryWrapper=new LambdaQueryWrapper<>();
//根据排序的降序排列
queryWrapper.orderByAsc(Category::getSort);
//以及执行查询
categoryService.page(pageInfo,queryWrapper);
return R.success(pageInfo);
}
分类管理的删除按钮
@DeleteMapping
public R delete(@PathVariable Long id){
categoryService.removeById(id);
return R.success("成功");
}
优化 我们点击删除按钮就会删除掉所有 也不知道分类下有没有菜品或者套餐
我们在service中定义一个接口
void remove(Long id);
在Impl中实现
public void remove(Long id) {
//添加查询条件
LambdaQueryWrapper queryWrapper1=new LambdaQueryWrapper();
queryWrapper1.eq(Dish::getCategoryId,id);
//统计
int count = dishService.count(queryWrapper1);
if (count>0){
throw new CustomException("当前分类下关联了菜品 不能删除");
//关联菜品 抛出一个业务异常
}
//查询是否关联了套餐 如果关联了套餐 就
LambdaQueryWrapper queryWrapper2=new LambdaQueryWrapper();
queryWrapper2.eq(Setmeal::getCategoryId,id);
int count1 = setmealService.count();
setmealService.count(queryWrapper2);
if (count1>0){
throw new CustomException("当前分类下关联了套餐 不能删除");
}
super.removeById(id);
}
我们需要定义一个全局异常 继承于RuntimeException
public CustomException(String msg){
super(msg);
}
并且在GlobaExceptionHandler处理我们的自定义异常
@ExceptionHandler(RuntimeException.class)
public R exception(RuntimeException e) {
return R.error(e.getMessage());
}
我们在控制层中从新调用remove方法
@DeleteMapping
public R delete(@PathVariable Long id){
categoryService.remove(id);
//categoryService.removeById(id);
return R.success("成功");
}
这样删除就完成了
分类管理中的修改按钮
@PutMapping
public R update(@RequestBody Category category){
categoryService.updateById(category);
return R.success("成功");
}



