Skip to content
DAILY QUOTE

“ ”

4.1.分页插件

在未引入分页插件的情况下,MybatisPlus是不支持分页功能的,IServiceBaseMapper中分页方法都无法正常起效。

所以必须配置分页插件。

4.1.1.配置分页插件

在项目中新建配置类:

java
package com.itheima.mp.config;  
  
import com.baomidou.mybatisplus.annotation.DbType;  
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;  
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
  
@Configuration  
public class MybatisConfig {  
    @Bean  
    public MybatisPlusInterceptor mybatisPlusInterceptor() {  
        //初始化核心插件  
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();  
        //添加分页插件  
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));  
        return interceptor;  
    }  
}

4.1.2.分页API

编写一个分页查询的测试:

java
@Test  
void testPageQuery() {  
    //1.分页查询,new Page()的两个参数分别是:页码、每页大小  
    Page<User> page = userService.page(new Page<>(2, 2));  
    //2.总条数  
    System.out.println("total=" + page.getTotal());  
    //3.总页数  
    System.out.println("pages=" + page.getPages());  
    //4.数据  
    List<User> records = page.getRecords();  
    records.forEach(System.out::println);  
}

测试: 常见api如下:

Java
int pageNo = 1, pageSize = 5;
// 分页参数
Page<User> page = Page.of(pageNo, pageSize);
// 排序参数, 通过OrderItem来指定
page.addOrder(new OrderItem("balance", false));

userService.page(page);

4.2.通用分页实体

现在要实现一个用户分页查询的接口,接口规范如下:

这里定义三个实体:

  • UserQuery:分页查询条件的实体,包含分页、排序参数、过滤条件
  • PageDTO:分页结果实体,包含总条数、总页数、当前页数据
  • UserVO:用户页面视图实体

4.2.1.实体

UserQuery代码如下:

java
package com.itheima.mp.domain.query;  
  
import io.swagger.annotations.ApiModel;  
import io.swagger.annotations.ApiModelProperty;  
import lombok.Data;  
  
@Data  
@ApiModel(description = "用户查询条件实体")  
public class UserQuery {  
    @ApiModelProperty("用户名关键字")  
    private String name;  
    @ApiModelProperty("用户状态:1-正常,2-冻结")  
    private Integer status;  
    @ApiModelProperty("余额最小值")  
    private Integer minBalance;  
    @ApiModelProperty("余额最大值")  
    private Integer maxBalance;  
}

其中缺少分页条件,而其他业务也有分页查询的需求,所以将分页查询条件单独定义为一个PageQuery实体:

java
package com.itheima.mp.domain.query;  
  
import io.swagger.annotations.ApiModel;  
import io.swagger.annotations.ApiModelProperty;  
import lombok.Data;  
  
@Data  
@ApiModel(description = "分页查询实体")  
public class PageQuery {  
    @ApiModelProperty("页码")  
    private Long pageNo;  
    @ApiModelProperty("每页数据条数")  
    private Long pageSize;  
    @ApiModelProperty("排序字段")  
    private String sortBy;  
    @ApiModelProperty("是否升序")  
    private Boolean isAsc;  
}

然后让UserQuery继承这个实体,这样UserQuery也就有这些属性了:

java
package com.itheima.mp.domain.query;  
  
import io.swagger.annotations.ApiModel;  
import io.swagger.annotations.ApiModelProperty;  
import lombok.Data;  
import lombok.EqualsAndHashCode;  
  
@EqualsAndHashCode(callSuper = true) //lombok生成equals和hashcode时,把父类里的字段也算进去  
@Data  
@ApiModel(description = "用户查询条件实体")  
public class UserQuery extends PageQuery {  
    @ApiModelProperty("用户名关键字")  
    private String name;  
    @ApiModelProperty("用户状态:1-正常,2-冻结")  
    private Integer status;  
    @ApiModelProperty("余额最小值")  
    private Integer minBalance;  
    @ApiModelProperty("余额最大值")  
    private Integer maxBalance;  
}

返回值的用户实体沿用UserVO实体,同时定义分页实体PageDTO

java
package com.itheima.mp.domain.vo;  
  
import io.swagger.annotations.ApiModel;  
import io.swagger.annotations.ApiModelProperty;  
import lombok.Data;  
  
import java.util.List;  
  
@Data  
@ApiModel(description = "分页结果")  
public class PageDTO<T> {  
    @ApiModelProperty("总条数")  
    private Long total;  
    @ApiModelProperty("总页数")  
    private Long pages;  
    @ApiModelProperty("集合")  
    private List<T> list;  
}

4.2.2.开发接口

接下来在UserController中定义分页查询用户接口:

java
@GetMapping("/page")  
public PageDTO<UserVO> queryUserPage(UserQuery query){  
    return userService.queryUsersPage(query);  
}

UserService创建方法,同时UserServiceImpl实现方法:

java
@Override  
public PageDTO<UserVO> queryUsersPage(UserQuery query) {  
    //1.构建条件  
    //1.1.分页条件  
    Page<User> pageParam=Page.of(query.getPageNo(),query.getPageSize());  
    //1.2.排序条件  
    if(StrUtil.isNotBlank(query.getSortBy())){  
        pageParam.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));  
    }else {  
        //默认按照更新时间顺序排序  
        pageParam.addOrder(new OrderItem("update_Time", false));  
    }  
    //2.查询  
    Page<User> page=lambdaQuery().eq(query.getStatus()!=null,User::getStatus,query.getStatus())  
            .like(query.getName()!=null,User::getUsername,query.getName())  
            .page(pageParam);  
    //3.数据非空校验  
    if(CollUtil.isEmpty(page.getRecords())){  
        //无数据,返回空结果  
        return new PageDTO<>(page.getTotal(),page.getPages(),Collections.emptyList());  
    }  
    //4.有数据,转换  
    List<UserVO> list=BeanUtil.copyToList(page.getRecords(), UserVO.class);  
    //5.封装返回  
    return new PageDTO<UserVO>(page.getTotal(),page.getPages(),list);  
}

测试效果:

4.2.3.改造PageQuery实体

PageQueryMybatisPlusPage转换过程是比较麻烦的。

因此在PageQuery实体中定义一个工具方法,简化开发。

pageQuery代码如下:

java
package com.itheima.mp.domain.query;  
  
import cn.hutool.core.util.StrUtil;  
import com.baomidou.mybatisplus.core.metadata.OrderItem;  
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;  
import io.swagger.annotations.ApiModel;  
import io.swagger.annotations.ApiModelProperty;  
import lombok.Data;  
  
@Data  
@ApiModel(description = "分页查询实体")  
public class PageQuery {  
    @ApiModelProperty("页码")  
    private Long pageNo;  
    @ApiModelProperty("每页数据条数")  
    private Long pageSize;  
    @ApiModelProperty("排序字段")  
    private String sortBy;  
    @ApiModelProperty("是否升序")  
    private Boolean isAsc;  
  
    public <T>Page<T> toMpPage(OrderItem ... items) {  
        //1.分页条件  
        Page<T> page = new Page<>(pageNo, pageSize);  
        //2.排序条件  
        if(StrUtil.isNotBlank(sortBy)){  
            //不为空  
            page.addOrder(new OrderItem(sortBy,isAsc));  
        }else if(items!=null){  
            //为空,默认排序  
            page.addOrder(items);  
        }  
        return page;  
    }  
  
    public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc){  
        return this.toMpPage(new OrderItem(defaultSortBy, isAsc));  
    }  
  
    public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {  
        return toMpPage("create_time", false);  
    }  
  
    public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {  
        return toMpPage("update_time", false);  
    }  
}

修改实现方法中的转换:

java
@Override  
public PageDTO<UserVO> queryUsersPage(UserQuery query) {  
    //1.构建条件  
    //1.1.分页条件  
    Page<User> pageParam= query.toMpPageDefaultSortByUpdateTimeDesc();  
    //2.查询  
    Page<User> page=lambdaQuery().eq(query.getStatus()!=null,User::getStatus,query.getStatus())  
            .like(query.getName()!=null,User::getUsername,query.getName())  
            .page(pageParam);  
    //3.数据非空校验  
    if(CollUtil.isEmpty(page.getRecords())){  
        //无数据,返回空结果  
        return new PageDTO<>(page.getTotal(),page.getPages(),Collections.emptyList());  
    }  
    //4.有数据,转换  
    List<UserVO> list=BeanUtil.copyToList(page.getRecords(), UserVO.class);  
    //5.封装返回  
    return new PageDTO<UserVO>(page.getTotal(),page.getPages(),list);  
}

4.2.4.改造PageDTO实体

查询出分页结果后,数据非空校验,数据vo转换都是模板代码,也可以封装到PageDTO工具方法中,代码如下:

java
public static <PO,VO>PageDTO<VO> of(Page<PO> p,Class<VO> voClass){ //构建当前类对象  
    PageDTO<VO> dto=new PageDTO<>();  
    //1.总条数  
    dto.setTotal(p.getTotal());  
    //2.总页数  
    dto.setPages(p.getPages());  
    //3.当前页数据  
    List<PO> records=p.getRecords();  
    if(CollUtil.isEmpty(records)){  
        dto.setList(Collections.emptyList());  
        return dto;  
    }  
    //4.拷贝user的VO  
    dto.setList(BeanUtil.copyToList(records, voClass));  
    //5.返回  
    return dto;  
}

最终,业务层到吗简化为:

java
@Override  
public PageDTO<UserVO> queryUsersPage(UserQuery query) {  
    //1.构建条件  
    //1.1.分页条件  
    //Page<User> pageParam=Page.of(query.getPageNo(),query.getPageSize());  
    Page<User> pageParam= query.toMpPageDefaultSortByUpdateTimeDesc();  
    //1.2.排序条件  
    if(StrUtil.isNotBlank(query.getSortBy())){  
        pageParam.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));  
    }else {  
        //默认按照更新时间顺序排序  
        pageParam.addOrder(new OrderItem("update_Time", false));  
    }  
    //2.查询  
    Page<User> page=lambdaQuery().eq(query.getStatus()!=null,User::getStatus,query.getStatus())  
            .like(query.getName()!=null,User::getUsername,query.getName())  
            .page(pageParam);  
    //3.封装VO结果  
    return PageDTO.of(page,UserVO.class);  
}

如果希望自定义PO到VO的转换过程,修改PageDTO代码如下:

java
public static <PO,VO>PageDTO<VO> of(Page<PO> p, Function<PO,VO> convertor){ //构建当前类对象  
    PageDTO<VO> dto=new PageDTO<>();  
    //1.总条数  
    dto.setTotal(p.getTotal());  
    //2.总页数  
    dto.setPages(p.getPages());  
    //3.当前页数据  
    List<PO> records=p.getRecords();  
    if(CollUtil.isEmpty(records)){  
        dto.setList(Collections.emptyList());  
        return dto;  
    }  
    //4.拷贝user的VO  
    dto.setList(records.stream().map(convertor).collect(Collectors.toList()));  
    //5.返回  
    return dto;  
}

dto.setList(records.stream().map(convertor).collect(Collectors.toList())); 说明:

遍历records里的每一个PO对象
把每个PO对象交给convertor转换
转换后的结果收集成List
设置到dto.list里

修改业务层代码:

java
@Override
@Override  
public PageDTO<UserVO> queryUsersPage(UserQuery query) {  
    //1.构建条件  
    //1.1.分页条件  
    Page<User> pageParam= query.toMpPageDefaultSortByUpdateTimeDesc();  
    //2.查询  
    Page<User> page=lambdaQuery().eq(query.getStatus()!=null,User::getStatus,query.getStatus())  
            .like(query.getName()!=null,User::getUsername,query.getName())  
            .page(pageParam);  
    //3.封装VO结果  
    return PageDTO.of(page,user->{  
        //1.拷贝基础属性  
        UserVO vo=BeanUtil.copyProperties(user,UserVO.class);  
        //2.处理特殊逻辑  
        vo.setUsername(vo.getUsername().substring(0,vo.getUsername().length()-2)+"**");  
        return vo;  
    });  
}

测试: