这个页面从哪里找呢?首先我们是登录进去,就是index.html,
没有开发分页查询之前,数据是不能正确展示出来的。现在我们就需要实现这儿分页查询的功能。
还是按照原来的分页查询的类似的操作,在vue点到这个页面的时候会自动执行一个分页查询。所以在vue中一定有一个挂载的自动执行的方法。
执行分页下面还有获取图片的方法请求,现在我们先不用管这个图片的加载的方法。我们句直接去进行分页功能的开发。
这里还是进行前后端交互,当获取到正确的响应的话,然后将具体的数据装载到前端的页面。就是这样的一个过程。
然后点进去这个方法其实具体还是写在一个里面,然后点击进去去查看这个具体的方法。
这个参数是什么呢?就是我们看到的参数,那这个参数就是具体的page,pageSize,还有name,那么我们就需要去接收这几个参数。
这个具体的后端的具体的请求路径和参数接收就知道怎么去接收了。
首先需要菜品的实体类。实体类的属性基本对应数据库字段。
我们按照数据库当中的字段就暂且这样写,其实后面咋页面展示的话,会有的数据没有展示出来。我们先这样去写。
package com.jgdabc.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
菜品
*/
@Data
public class Dish implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//菜品名称
private String name;
//菜品分类id
private Long categoryId;
//菜品价格
private BigDecimal price;
//商品码
private String code;
//图片
private String image;
//描述信息
private String description;
//0 停售 1 起售
private Integer status;
//顺序
private Integer sort;
@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;
//是否删除
private Integer isDeleted;
}
然后dao层,也就是我们的mapper层。
package com.jgdabc.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jgdabc.entity.Dish;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DishMapper extends BaseMapper<Dish> {
}
然后service层
package com.jgdabc.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jgdabc.dto.DishDto;
import com.jgdabc.entity.Dish;
public interface DishService extends IService<Dish> {
//新增菜品,同时插入口味数据
然后service的实现类
package com.jgdabc.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jgdabc.dto.DishDto;
import com.jgdabc.entity.Dish;
import com.jgdabc.entity.DishFlavor;
import com.jgdabc.mapper.DishMapper;
import com.jgdabc.service.DishFlavorService;
import com.jgdabc.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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;
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
}
按照这样的逻辑我们去实现Controller的分页功能。我们先按照遮掩这样的逻辑去实现我们的分页功能。
那就先这样去写。
我们可以一步一步来,我们先看看这些具体的参数。
@GetMapping("/page")
public R_<Page> page(int page, int pageSize, String name) {
log.info("page:{}", page);
log.info("pageSize:{}", pageSize);
log.info("name{}", name);
return null;
来打断点看看这些数据
我们现在只是打开这个页面的时候它就会执行分页查询。 对的传来默认的当前页面为第一页,然后具体的每页的大小为10。但是name为什么为null呢?
因为这里我们没有输入菜品名称,所以传来一个空的name对象属性。
于是我们可以确认这是一个条件分页查询 我们可以去进一步改善的就是我们需要去按照条件去执行分页条件查询。其实这样的话很类似动态sql。
于是我们可以进一步的去做这个分页条件查询。于是我们写出这样的代码
@GetMapping("/page")
public R_<Page> page(int page, int pageSize, String name) {
log.info("page:{}", page);
log.info("pageSize:{}", pageSize);
log.info("name{}", name);
构造一个分页构造器对象
Page<Dish> dishPage = new Page<>(page, pageSize);
构造一个分页条件构造器
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
根据name去添加条件,作为查询的条件,这个名字啊
我们最好去用迷糊查询
queryWrapper.like(name!=null,Dish::getName,name);
然后做一个排序的条件
queryWrapper.orderByDesc(Dish::getUpdateTime);
做分页查询具体
dishService.page(dishPage,queryWrapper);//最后的数据表其实已经自动处理封装到dishPage里面
返回给前端以R_对象封装的数据对象
return R_.success(dishPage);
通过调试可以知道具体的数据就是封装了dishPage里面。
然后放行下来到了页面展示出来,图片没有展示出来正常吗,是因为我们没有设置图片数据文件上传这些操作,它是具体的图片数据没有出来,但是我们的菜品分类却是空的。
哦对啊,我们的dish实体类中就没有这个字段,对应的数据库表中也没有这个字段。所以最后查询是不会封装该数据的。于是我们就需要扩展出来这个字段,那么我们就需要去扩展实体类,然后我们设置这样的一个DishDto类。
package com.jgdabc.dto;
import com.jgdabc.entity.Dish;
import com.jgdabc.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class DishDto extends Dish {
//我们现在只用到这个属性,后面我们还会扩展属性
private String categoryName;
}
这个类不需要去写dao,mapper,service以及实现这些,我们用这个dto只是为了对数据属性进行的一个扩展。
然后后面就是重头戏了,初次看的话感觉有点绕,但是多看看就好了。 下面去改进Controller里面这个具体的分页查询的功能。完整的写出来。 要对照着这个分页对象里面的属性去理解,开始我们下面的操作。
我将每一步都尽力去写的注释,注意这里上面Controller要注入 bean。
@GetMapping("/page")
public R_<Page<DishDto>> page(int page, int pageSize, String name) {
//构造一个分页构造器对象
Page<Dish> dishPage = new Page<>(page, pageSize);
Page<DishDto> dishDtoPage = new Page<>(page, pageSize);
//上面对dish泛型的数据已经赋值了,这里对DishDto我们可以把之前的数据拷贝过来进行赋值
//构造一个条件构造器
LambdaQueryWrapper<Dish>
[video(video-Wo30nm2C-1660748796893)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=213091208&page=61)(image-https://img-blog.csdnimg.cn/img_convert/e994eeca6254ad799539866cd8b25a82.png)(title-业务开发Day4-14-菜品信息分页查询)]
queryWrapper = new LambdaQueryWrapper<>();
//添加过滤条件 注意判断是否为空 使用对name的模糊查询
queryWrapper.like(name != null, Dish::getName, name);
//添加排序条件 根据更新时间降序排
queryWrapper.orderByDesc(Dish::getUpdateTime);
//去数据库处理分页 和 查询
dishService.page(dishPage, queryWrapper);//这样是原始的未扩展的分页查询的数据的封装。
//获取到dish的所有数据 records属性是分页插件中表示分页中所有的数据的一个集合
List<Dish> records = dishPage.getRecords();
// item代表遍历出来的每一个菜品就是Dish
// 这里类似一个遍历属性赋值的过程。
List<DishDto> list = records.stream().map((item) -> {
//对实体类DishDto进行categoryName的设值
DishDto dishDto = new DishDto();
//这里的item相当于Dish 对dishDto进行除categoryName属性的拷贝
BeanUtils.copyProperties(item, dishDto);
//获取分类的id
Long categoryId = item.getCategoryId();
//通过分类id获取分类对象
Category category = categoryService.getById(categoryId);
if (category != null) {
//设置实体类DishDto的categoryName属性值。这里是调用到category的查询查询到name然后赋值给具体的dto中扩展的属性
String categoryName = category.getName();
dishDto.setCategoryName(categoryName);
}
return dishDto;//返回每一个dto
}).collect(Collectors.toList());//这里收集起来给到列表
//对象拷贝 使用框架自带的工具类,第三个参数是不拷贝到属性
BeanUtils.copyProperties(dishPage, dishDtoPage, "records");//除去records以外的属性的拷贝,因为我们的records单独处理了。
dishDtoPage.setRecords(list);//将收集起来的list赋值给最终的dto的records
//因为上面处理的数据没有分类的id,这样直接返回R.success(dishPage)虽然不会报错,但是前端展示的时候这个菜品分类这一数据就为空
//所以进行了上面的一系列操作
return R_.success(dishDtoPage);//最终返回。
}
但是还是要去多看看,多听听老师的讲解。
这个records按照我的理解的话,为什么要分开拷贝呢?其实你看它前面有一个泛型的修饰,我们之前的泛型是Dish这个实体类,如果我们直接拷贝过去的话,是不符合我们扩展的实体类泛型类型的,所以我们最终单独对其属性进行处理,将最终收集起来的数据设置了进去,这样就会符合一个2泛型的要求。
最终的展示