
本文共 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);Listlist;if(param1 != null){ list = countryMapper.selectIf(param1);} else { list = new ArrayList ();}
这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。
上面这个代码,应该写成下面这个样子:
Listlist;if(param1 != null){ PageHelper.startPage(1, 10); list = countryMapper.selectIf(param1);} else { list = new ArrayList ();}
这种写法就能保证安全。
如果你对此不放心,你可以手动清理 ThreadLocal
存储的分页参数,可以像下面这样使用:
Listlist;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的一些常见问题及其解决方案,希望对你有所帮助
发表评论
最新留言
关于作者
