springboot实现查询语句的分页处理
1. 综述
springboot中实现分页的方法有很多,我大体上只看了3种,分别为mybatis-plus自带分页插件、hutool自带分页工具和pageheper实现分页,详细情况如下:
2. mybatis-plus实现分页
MyBatis-Plus 的分页插件 PaginationInnerInterceptor 提供了强大的分页功能,支持多种数据库,使得分页查询变得简单高效。
这是mp自带的分页插件,不过好像用的不多,我看了一下,主要是通过在启动类上面加注解扫描mapper文件包实现的,这就要求所有的mapper必须在同一个包下且PaginationInnerInterceptor 仅用于数据库分页,并不能实现给个list分页
于mybatis-plus v3.5.9 起,PaginationInnerInterceptor 已分离出来。如需使用,则需单独引入 mybatis-plus-jsqlparser 依赖

如果你需要支持的数据库不在列表中,可以通过 Pull Request 请求添加。
添加分页配置插件:
@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {
/**
* 添加分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
}
配置文件可供配置属性介绍:
PaginationInnerInterceptor 提供了以下属性来定制分页行为:
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| overflow | boolean | false | 溢出总页数后是否进行处理 |
| maxLimit | Long | 单页分页条数限制 | |
| dbType | DbType | 数据库类型 | |
| dialect | IDialect | 方言实现类 |
建议单一数据库类型的均设置 dbType
自定义 Mapper 方法中使用分页
你可以通过以下方式在 Mapper 方法中使用分页:
IPage<UserVo> selectPageVo(IPage<?> page, Integer state);
// 或者自定义分页类
MyPage selectPageVo(MyPage page);
// 或者返回 List
List<UserVo> selectPageVo(IPage<UserVo> page, Integer state);
对应的 XML 配置:
<select id="selectPageVo" resultType="xxx.xxx.xxx.UserVo">
SELECT id,name FROM user WHERE state=#{state}
</select>
如果返回类型是 IPage,则入参的 IPage 不能为 null。如果想临时不分页,可以在初始化 IPage 时 size 参数传入小于 0 的值。 如果返回类型是 List,则入参的 IPage 可以为 null,但需要手动设置入参的 IPage.setRecords(返回的 List)。 如果 XML 需要从 page 里取值,需要使用 page.属性 获取。
我这里没有用上述方法,直接用的mybatis-plus自带的selectPage实现的分页查询
其他注意事项
- 生成 countSql 时,如果 left join 的表不参与 where 条件,会将其优化掉。建议在任何带有 left join 的 SQL 中,都给表和字段加上别名。
- 在使用多个插件时,请将分页插件放到插件执行链的最后面,以避免 COUNT SQL 执行不准确的问题。
Page 类
Page 类继承了 IPage 类,实现了简单分页模型。如果你需要实现自己的分页模型,可以继承 Page 类或实现 IPage 类。
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| records | List |
emptyList | 查询数据库列表 |
| total | Long | 0 | 查询列表总记录数 |
| size | Long | 10 | 每页显示条数,默认10 |
| current | Long | 1 | 当前页 |
| orders | List |
emptyList | 排序字段信息 |
| optimizeCountSql | boolean | true | 自动优化 COUNT SQL |
| optimizeJoinOfCountSql | boolean | true | 自动优化 COUNT SQL 是否把 join 查询部分移除 |
| searchCount | boolean | true | 是否进行 count 查询 |
| maxLimit | Long | 单页分页条数限制 | |
| countId | String | XML 自定义 count 查询的 statementId |
这是mybatis-plus自带的Page类可以用来继承,分页使用,但是字段太多,也可以自己挑几个字段封装成新的Page类
由于分页了,所以数据量一般会很大,我们实现方法为分为了两个接口,第一个接口用于将分页数据同步到数据库,第二个就用来从数据库分页查询,关键点在于第一个同步到数据库会出现多线程操作数据,数据异常,加分布式锁还不能阻塞等待,那样查询时间会更慢,解决办法:创建ConcurrentHashMap<String, Boolean>和Map<String, List
springboot中自带分页插件应用
mybatis-plus官网分页插件介绍
3. hutool分页工具类
hutool工具类中的分页类主要是返回分页所需的数组,如果要用需要自己建包装类,包装类的具体内容需要与前端协商好,这是我最初用的分页工具,用着还行吧,代码量有点大,虽然很基础
导入hutool工具类依赖
implementation 'cn.hutool:hutool-all:5.8.10'
Mapper
@Select("select * from busi_commission order by id limit #{countonepage} offset (#{pageno}-1) * #{countonepage}")
List<Commmission> selectall(Integer pageno, Integer countonepage);
pageno:当前页数 countonepage:每页数据条数 displaycount分页所要展示的页数 下面都将是这样的意思
limit offset 不理解的可以看这个:菜鸟教材limit详解
Service
public List<Commmission> selectall(Integer pageno, Integer countonepage){
return commissionMapper.selectall(pageno, countonepage);
}
ReturnResult包装类
点击查看代码
import lombok.Data;
@Data
public class ReturnResult {
// 状态码
private int code;
// 消息
private String msg;
// 数据
private Object data;
private ReturnResult (){
}
private static ReturnResult buildResult(int code, String msg, Object data) {
ReturnResult result = new ReturnResult();
result.code = code;
result.msg = msg;
result.data = data;
return result;
}
public static ReturnResult buildSuccessResult(String msg, Object data) {
return buildResult(200, msg, data);
}
public static ReturnResult buildSuccessResult(Object data) {
return buildSuccessResult("success", data);
}
public static ReturnResult buildFailureResult(int code, String msg, Object data) {
return buildResult(code, msg, data);
}
public static ReturnResult buildFailureResult(String msg, Object data) {
return buildFailureResult(500, msg, data);
}
public static ReturnResult buildFailureResult(String msg) {
return buildFailureResult(500, msg, null);
}
}
这个包装类是我们做项目所用,如果个人没需求可以不用,不过后面的Controller会用到
PageResult分页包装类
点击查看代码
import cn.hutool.core.util.PageUtil;
import lombok.Data;
@Data
public class PageResult {
private Integer current_page;
private Integer page_size;
private Integer total;
private Integer totalpage;
private Object data;
private int[] displaycount;
public PageResult() {
}
public static PageResult buildPage(Integer current_page, Integer page_size, Integer total,Integer displaycount, Object data) {
PageResult result = new PageResult();
result.current_page = current_page;
result.page_size = page_size;
result.total = total;
if (total % page_size != 0) {
result.totalpage = total / page_size+1;
}else {
result.totalpage = total / page_size;
}
result.displaycount = PageUtil.rainbow(current_page, result.totalpage, displaycount);
result.data = data;
return result;
}
}
Controller
@GetMapping()
public ReturnResult getAllCommission(Integer pageno,Integer countonepage,Integer displaycount){
return ReturnResult.buildSuccessResult(buildPage(pageno,countonepage,commissionService.getcount(),displaycount,commissionService.selectall(pageno,countonepage)));
}
hutool官网分页介绍:hutool官网分页工具类
这个工具类在PageResult中有用到
3. Pagehelper实现分页(SQL语句有注意事项)
Pagehelper是mybatis的,所以用它是需要写SQL语句的,是不能用mybtis-plus自动生成的,但是它使用更加简便
导入依赖
implementation 'com.github.pagehelper:pagehelper-spring-boot-starter:1.4.5'
Mapper
@Select("select * from busi_commission order by id desc")
List<Commmission> selectall();
这里加了个根据ID逆序排序
注意:这里的mapper中的SQL语句不能有分号,因为pageheper会调用两次SQL语句,第二次有limit,加分好limit加不进去,会报错
Service
public PageInfo<Commmission> selectall(Integer pageno, Integer countonepage) {
PageHelper.startPage(pageno, countonepage);
List<Commmission> result = commissionMapper.selectall();
return new PageInfo<>(result);
}
Controller
@GetMapping()
public ReturnResult getAllCommission(Integer pageno,Integer countonepage){
return ReturnResult.buildSuccessResult(commissionService.selectall(pageno,countonepage));
}

浙公网安备 33010602011771号