PageHelper
添加maven依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.8</version>
</dependency>
在Mybatis的配置文件 Mybatis-Config.xml中配置PageHelper插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="oracle"/>
<property name="offsetAsPageNum" value="false"/>
<property name="rowBoundsWithCount" value="false"/>
<property name="pageSizeZero" value="true"/>
<property name="reasonable" value="false"/>
<property name="supportMethodsArguments" value="false"/>
<property name="returnPageInfo" value="none"/>
</plugin>
</plugins>
- plugins插件的配置在 settings之后 在environments之前
- settings中设置Mybatis的一些额外的运行参数 如是否开启延迟加载,动态代理使用CG-LIB,或JAVALIB等;
原理
pageHelper会使用ThreadLocal获取到同一线程中的变量信息,各个线程之间的Threadlocal不会相互干扰,也就是Thread1中的ThreadLocal1之后获取到Tread1中的变量的信息,不会获取到Thread2中的信息
所以在多线程环境下,各个Threadlocal之间相互隔离,可以实现,不同thread使用不同的数据源或不同的Thread中执行不同的SQL语句
所以,PageHelper利用这一点通过拦截器获取到同一线程中的预编译好的SQL语句之后将SQL语句包装成具有分页功能的SQL语句,并将其再次赋值给下一步操作,所以实际执行的SQL语句就是有了分页功能的SQL语句
注意
PageHelper只对紧跟着的第一个SQL语句起作用。所以若一个方法中涉及到多个查询,需要小心,避免为不需要分页的添加了分页,而真正需要分页的却没有被分页。
使用
1)、统计总数,(将SQL语句变为 select count(0) from xxx,只对简单SQL语句其效果,复杂SQL语句需要自己写)
Page<?> page = PageHelper.startPage(1,-1);
long count = page.getTotal();
2)、分页,pageNum - 第N页, pageSize - 每页M条数
A、只分页不统计(每次只执行分页语句)
PageHelper.startPage([pageNum],[pageSize]);
List<?> pagelist = queryForList( xxx.class, "queryAll" , param);
//pagelist就是分页之后的结果
B、分页并统计(每次执行2条语句,一条select count语句,一条分页语句)适用于查询分页时数据发生变动,需要将实时的变动信息反映到分页结果上
Page<?> page = PageHelper.startPage([pageNum],[pageSize],[iscount]);
List<?> pagelist = queryForList( xxx.class , "queryAll" , param);
long count = page.getTotal();
//也可以 List<?> pagelist = page.getList(); 获取分页后的结果集
3)、使用PageHelper查全部(不分页)
PageHelper.startPage(1,0);
List<?> alllist = queryForList( xxx.class , "queryAll" , param);
4)、PageHelper的其他API
String orderBy = PageHelper.getOrderBy(); //获取orderBy语句
Page<?> page = PageHelper.startPage(Object params);
Page<?> page = PageHelper.startPage(int pageNum, int pageSize);
Page<?> page = PageHelper.startPage(int pageNum, int pageSize, boolean isCount);
Page<?> page = PageHelper.startPage(pageNum, pageSize, orderBy);
Page<?> page = PageHelper.startPage(pageNum, pageSize, isCount, isReasonable); //isReasonable分页合理化,null时用默认配置
Page<?> page = PageHelper.startPage(pageNum, pageSize, isCount, isReasonable, isPageSizeZero); //isPageSizeZero是否支持PageSize为0,true且pageSize=0时返回全部结果,false时分页,null时用默认配置
默认值
//RowBounds参数offset作为PageNum使用 - 默认不使用
private boolean offsetAsPageNum = false;
//RowBounds是否进行count查询 - 默认不查询
private boolean rowBoundsWithCount = false;
//当设置为true的时候,如果pagesize设置为0(或RowBounds的limit=0),就不执行分页,返回全部结果
private boolean pageSizeZero = false;
//分页合理化
private boolean reasonable = false;
//是否支持接口参数来传递分页参数,默认false
private boolean supportMethodsArguments = false;
坑
PageHelp 在获取 count 的时候 过滤 order by 导致 总数不正确问题
pageHelp 获取count的时候会默认把order by 过滤掉,有可能会导致实际总数与查出来的总数不一样的情况。只要在需要不过滤的order by 前面添加 /
keep orderby
/ 注解后,pageHelp 就会忽略不过滤order by。
mybaits中使用pageHelper 进行一对都分页时结果不对的处理方式
- pageHelper遇到resultMap的collection后,分页总数不对。
由于PageHelper分页总数是根据count(0)来计算出来的(即自动生成一条SQL select count(0) from xx where 筛选条件),而collection会把结果集合并(一对多的情况),计算总数在合并结果集之前,所以计算的总数不对。
- pageHelper遇到resultMap的collection后,分页结果集不对。
同计数的原理一样,分页实际是在合并结果集之前进行的(即直接在查询SQL语句后面加了limit x,x),这就导致了存在一对多情况时,实际返回的结果集个数与分页要求的每页结果集个数不一致,且如果最后一条记录也涉及一对多时,结果集内容也不一定准确。
- 解决方法
需要使用pageHelper分页时,resultMap不要用嵌套结果的方式,可以使用嵌套查询的方式
spring mvc+mybatis项目中,当使用PageHelper插件进行分页查询时,查到的总数据量值是正确的,但是查询当前页返回的列表个数不对。比如每页查询10条,返回2条或者3条。resultMap使用了association返回复杂属性。
- 原因
是当resultMap使用<result /> <association/>返回,当<result />对应的属性有重复值时,只加载一个。是当resultMap使用<result /> <association/>返回,当<result/>对应的属性有重复值时,只加载一个。
- 解决方法:
resultMap中增加<id />的返回,保证数据的唯一性。