PageHelper 地址:https://pagehelper.github.io/

Maven依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>最新版本</version>
</dependency>

或者直接用 二选一

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>

PageHelper配置类

import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class PageHelperConfig {

    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true"); // 将该参数设置为 true 后,offset会当成 pageNum 使用,limit 和 pageSize 含义相同。
        p.setProperty("reasonable", "true"); // reasonable 为 true,这时如果 pageNum<=0 会查询第一页,如果 pageNum>总页数 会查询最后一页。
        p.setProperty("dialect", "mysql"); // 配置mysql数据库
        pageHelper.setProperties(p);
        return pageHelper;
    }
}

PageHelper 主要用法

在serviceimpl 执行mapper前 加入 PageHelper.startPage(page, pageSize)。

说明:startPage是个静态方法,他的作用白话是:紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。但是要深入记忆的一点是:startPage()实现与ThreadLocal一样:是执行startPage()时,会记录线程信息,之后的此线程第一次Select会被执行分页。分页后,PageHelper会在其自己finally块执行clearPage()。

PageHelper乱分页问题产生原因

List<User> list;
PageHelper.startPage(1, 10);
if(param1 != null){
    list = userMapper.selectIf(param1);
} else {
    list = new ArrayList<User>();
}

上文代码看似没啥问题,但是要记住PageHelper.startPage是线程级别的分页,一旦这个线程A出现异常,但是这个PageHelper没有对线程A执行PageHelper.clearPage();就会导致下个接口使用线程A时,出现各种各样的异常。所以最保险的情况就是

    PageHelper.startPage(1, 10);
    try{
        // todo 做业务查询
    } finally {
        PageHelper.clearPage();
    }

最后附上日常开发API

        PageHelper.clearPage(); // 清除此线程的下次查询的分页
        // PageHelper.startPage(page, pageSize,false); // 通过PageInfo得到的total是-1
        // PageHelper.startPage(page, pageSize,true); 等价于 PageHelper.startPage(page, pageSize);
        PageHelper.startPage(page, pageSize); //此语句会PageHelper自动执行有count计数 可通过PageInfo.getTotal(),得到查询的结果数。
        new PageInfo<>(xxxMapper.selectByAllWithCondition(obj));

或者

PageHelper.startPage(pageNo, pageSize);

// 执行查询
List<YourEntity> list = yourMapper.selectAll();

// 获取分页信息(PageHelper会自动计算total)
PageInfo<YourEntity> pageInfo = new PageInfo<>(list);

附上一个工具类

推荐看完上文,了解基本信息。(可以找Gpt进行优化与拓展)

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import java.util.*;
import java.util.function.Supplier;

/**
 * 轻量分页工具:仅负责启动分页并返回 PageInfo。
 * 特性:
 * 1. 兼容 JDK8(不使用 String.isBlank)。
 * 2. 支持可选 orderBy,但做白名单过滤防止 SQL 注入。
 * 3. 统一页码/尺寸安全处理并限制最大 pageSize。
 */
public final class SimplePage {

    // 展示使用方式
    public static void main(String[] args) {
        int pageNum = 1;
        int pageSize = 10;
//        下面放了2个可使用的案例
//        PageInfo<Object> page = SimplePage.page(pageNum, pageSize,
//                () -> aMapper.selectList());
//
//        PageInfo<Object> page1 = SimplePage.page(pageNum, pageSize, "drop_rate desc",
//                () -> aMapper.selectList());
    }


    // 允许的排序列(根据实际表字段维护)
    private static final Set<String> ORDER_BY_WHITELIST =
            new HashSet<>(Arrays.asList("id", "create_time", "update_time", "drop_rate"));

    private static final int DEFAULT_PAGE_NUM = 1;
    private static final int DEFAULT_PAGE_SIZE = 10;
    private static final int MAX_PAGE_SIZE = 500;

    private SimplePage() {}

    public static <T> PageInfo<T> page(int pageNum, int pageSize, Supplier<List<T>> supplier) {
        PageHelper.startPage(normalizePageNum(pageNum), normalizePageSize(pageSize));
        return buildPageInfo(supplier);
    }

    public static <T> PageInfo<T> page(int pageNum, int pageSize, String orderBy, Supplier<List<T>> supplier) {
        int pn = normalizePageNum(pageNum);
        int ps = normalizePageSize(pageSize);
        String safeOrderBy = buildSafeOrderBy(orderBy);
        if (safeOrderBy != null) {
            PageHelper.startPage(pn, ps, safeOrderBy);
        } else {
            PageHelper.startPage(pn, ps);
        }
        return buildPageInfo(supplier);
    }

    private static <T> PageInfo<T> buildPageInfo(Supplier<List<T>> supplier) {
        List<T> list = supplier == null ? Collections.emptyList() : supplier.get();
        if (list == null) {
            list = Collections.emptyList();
        }
        return new PageInfo<>(list);
    }

    private static int normalizePageNum(int v) {
        return v < 1 ? DEFAULT_PAGE_NUM : v;
    }

    private static int normalizePageSize(int v) {
        if (v < 1) return DEFAULT_PAGE_SIZE;
        return Math.min(v, MAX_PAGE_SIZE);
    }

    private static boolean hasText(String s) {
        return s != null && !s.trim().isEmpty();
    }

    /**
     * 解析并校验 orderBy(示例支持: column [asc|desc],多列可按需扩展)
     */
    private static String buildSafeOrderBy(String raw) {
        if (!hasText(raw)) return null;
        String trimmed = raw.trim();
        // 拆分(只允许一列,若需多列可 split(",") 再循环校验)
        String[] parts = trimmed.split("\\s+");
        String col = parts[0].toLowerCase(Locale.ROOT);
        if (!ORDER_BY_WHITELIST.contains(col)) {
            return null; // 非白名单列,忽略排序
        }
        String direction = "asc";
        if (parts.length > 1) {
            String d = parts[1].toLowerCase(Locale.ROOT);
            if ("desc".equals(d) || "asc".equals(d)) {
                direction = d;
            }
        }
        return col + " " + direction;
    }
}
特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤

免责声明:
本站文章旨在总结学习互联网技术过程中的经验与见解。任何人不得将其用于违法或违规活动!所有违规内容均由个人自行承担,与作者无关。