PageHelper在Mybatis中的使用
环境:Spring 4.2.1 Mybatis 3.2.8 pagehelper 5.1.2
Mybatis官方教程:https://github.com/pagehelper/Mybatis-PageHelper/blob/d5947437cc6272cb3f1b186cadee74f1f8072cbb/wikis/zh/HowToUse.md
-
加入pageHelper依赖
com.github.pagehelper
pagehelper
5.1.2
-
在Mybatis-config.xml中配置pageHelper的拦截器
-
调用startPage()分页方法,在获取数据后将数据放到PageInfo对象中。
PageHelper.startPage(page, pageSize);
List<Map<String, Object>> list = itemMapper.getItems();
PageInfo<Map<String, Object>> pageInfor = new PageInfo<Map<String, Object>>(list);
即可对数据进行分页处理。
Mybatis使用pageHelper分页出现的问题
在pageHelper的文档中,我们可以看到这样的提示分页插件不支持嵌套结果映射(https://github.com/pagehelper/Mybatis-PageHelper/blob/d5947437cc6272cb3f1b186cadee74f1f8072cbb/wikis/zh/Important.md),由于嵌套结果方式会导致结果集被折叠,因此分页查询的结果在折叠后总数会减少,所以无法保证分页结果数量正确。这时候对于一些嵌套查询来说使用通用pageHelper已经不能用了,因此需要我们通过手动分别查询分页数据以及分页数据的映射数据。
通过使用一个例子对pageHelper进行测试不兼容嵌套查询的结果映射:
/Service层代码/
public List<Map<String, Object>> getOrdersByUserId(String userId) {
PageHelper.startPage(1, 2);
List<Map<String, Object>> list = orderMapper.getOrdersByUserId(userId);
return list;
}
通过嵌套查询返回一个Map对象并嵌套了另一个表中的多条数据(List集合),在取出数据后,可以看到这样的结果:

可以发现,pageHelper对我们的子数据进行了分页,我们要两条数据且只是出现了一条数据,这个时候,就只有通过分别查询来取出数据了。
首先,对订单数据不进行关联查询,先把数据取出来,然后根据取出来的订单对象,再把关联的信息查出来,这样就可以使用pageHelper来进行操作了。在Service层的代码如下:
public List<Map<String, Object>> getAnotherOrdersByUserId(String userId) {
PageHelper.startPage(1, 2);
List<Map<String, Object>> orderMaps = orderMapper.getAnotherOrdersByUserId(userId);
for (Map<String, Object> map : orderMaps) {
String orderId = (String) map.get("orderId");
List<Map<String, Object>> items = orderMapper.getItems(orderId);
map.put("items", items);
}
PageInfo pageInfor = new PageInfo(orderMaps);
System.out.println(pageInfor.getPageNum());
System.out.println(pageInfor.getTotal());
return orderMaps;
}
mapper的代码:
这样通过分别查询就可以避免了pageHelper的联合查询的问题。
正确的数据显示:

Demo:https://github.com/esileme/MybatisPager
PageHelper分页原理
在Mybatis中,提供了一个Interceptor接口,Mybatis的PageInterceptor类实现了Interceptor接口,在这个接口中,MyBatis允许我们拦截四个方法(ParameterHandler、ResultSetHandler、StatementHandler、Executor),可以对这四个方法进行拦截并实现相应的操作。
我们可以自定义实现Interceptor方式对Mybatis返回为Map的对象进行数据库数据与pojo对象映射的操作:
-
在Mybatis-config.xml中配置
-
code
package com.yl.page.intercpter;
import java.sql.Statement;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;@Intercepts(
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }))
public class CameHumpIntercpter implements Interceptor {public Object intercept(Invocation invocation) throws Throwable {
List

浙公网安备 33010602011771号