PageHelper常见问题
发布日期:2025-05-01 14:01:18 浏览次数:1 分类:技术文章

本文共 2511 字,大约阅读时间需要 8 分钟。

PageHelper.startPage方法重要提示

只有紧跟在 PageHelper.startPage 方法后的第一个 Mybatis 的查询(Select)方法会被分页。

请不要配置多个分页插件

请不要在系统中配置多个分页插件(使用 Spring 时,mybatis-config.xml 和 Spring<bean> 配置方式,请选择其中一种,不要同时配置多个分页插件)!

分页插件不支持带有 for update 语句的分页

对于带有 for update 的 sql,会抛出运行时异常,对于这样的 sql 建议手动分页,毕竟这样的 sql 需要重视。

为什么不支持一对一和一对多结果映射的分页查询?

在一对一和一对多时,根据分页条件查询出 100 条数据时,由于一对一和一对多会去重,经过嵌套处理后数据量会减少,因此分页想要获得 100 条数据无法实现。想要支持这种情况可以使用嵌套查询。嵌套查询是要额外执行SQL,主SQL可以得到正确的结果数量,因此可以正常分页。

 不安全的分页?

PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。

只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。

如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。

但是如果你写出下面这样的代码,就是不安全的用法:

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

这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。

上面这个代码,应该写成下面这个样子:

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

这种写法就能保证安全。

如果你对此不放心,你可以手动清理 ThreadLocal 存储的分页参数,可以像下面这样使用:

List
list;if(param1 != null){ PageHelper.startPage(1, 10); try{ list = countryMapper.selectAll(); } finally { PageHelper.clearPage(); }} else { list = new ArrayList
();}

常见问题

1. 分页参数失效

  • 问题描述:在开启分页后对查询的集合进行增删操作,或者通过stream处理分页结果集生成新集合,这可能导致分页参数失效,因为这些操作只影响内存中的集合,不影响数据库中的数据分布和分页设置。
  • 解决方案:确保在分页查询后不修改集合,或者在修改后重新设置分页参数。

2. 多limit的情况

  • 问题描述:使用线程池时,由于ThreadLocal与线程复用导致的“污染”,可能会导致多个查询共用同一个分页参数,从而影响分页结果。
  • 解决方案:确保每次分页查询后紧跟着执行查询操作,或者使用PageHelper.clearPage()手动清理分页参数。

3. 查询全部数据

  • 问题描述:分页查询失效,查询了全部数据。
    • PageHelper.startPage(1,0):当pageSize<=0时,不分页,也不会在SQL末尾拼接limit
    • 错误配置reasonable:设置reasonable=true时,若用户传入页数大于总页数,会修改查询页数,查询最后一页数据;当禁用此参数或设为false,若用户传入页数大于总页数,则返回为空。
    • 没有配置拦截器插件:确保MyBatis配置中正确配置了PageHelper作为拦截器插件。
  • 解决方案:正确配置reasonable属性,确保分页参数正确,以及正确配置MyBatis拦截器插件。

4. 其他注意事项

  • 问题描述
    • 确保PageHelper.startPage()被正确使用,必须在Mapper的查询方法之前调用,并且确保该查询方法会消费掉分页设置。
    • Stream流导致分页失效的问题:使用Stream流处理分页结果集后返回的数据类型为ArrayList,这可能导致分页失效。
    • 避免性能问题:MyBatis-PageHelper是通过动态修改SQL来实现分页的,这在大量或高并发场景下可能导致性能瓶颈。
    • 注意查询语句复杂度:对于复杂的查询语句,Mybatis-PageHelper可能会出现问题。
    • 测试分页逻辑:在实际应用中,彻底测试分页逻辑是非常重要的,以确保分页功能按照预期工作。
  • 解决方案
    • 确保分页方法调用后紧跟着查询操作,避免使用Stream流处理后不重新设置分页参数。
    • 对于大数据量的表,分页查询可能会带来性能问题,可以通过增加索引、优化SQL查询等方式提高性能。

以上是PageHelper的一些常见问题及其解决方案,希望对你有所帮助

上一篇:PageHelper引发的“幽灵数据”,怎么回事?
下一篇:PageHelper实现分页详细版、整合SSM应用

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2025年04月25日 06时12分32秒