使⽤com.github.pagehelper插件分页、count分析
pagehelper侵⼊研究
mybatis插件中有⼀个org.apache.ibatis.plugin.Interceptor,主要⽤于mybatis插件的植⼊。pagehelper的PageInterceptor实现了Interceptor,PageInterceptor在所有执⾏query操作时插⼊拦截。
PageInterceptor 分页器跳过分页
//调⽤⽅法判断是否需要进⾏分页,如果不需要,直接返回结果
if (!dialect.skip(ms, parameter, rowBounds)) {
...
}
public boolean skip(MappedStatement ms, Object parameterObject, RowBounds rowBounds) {
Id().endsWith(MSUtils.COUNT)){
throw new RuntimeException("在系统中发现了多个分页插件,请检查系统配置!");
}
//获取分页参数成功,则分页,获取失败,则跳过分页
Page page = Page(parameterObject, rowBounds);
if (page == null) {
return true;
} else {
//设置默认的 count 列
if(StringUtil.CountColumn())){
page.CountColumn());
}
autoDialect.initDelegateDialect(ms);
return false;
}
}
从skip⽅法可以看出,跳过分页的重点在Page。
//如果当前threadlocal中有page取当前threadlocal中的page
Page page = LocalPage();
if (page == null) {
// 不⼈为修改时rowBounds = RowBounds.DEFAULT
if (rowBounds != RowBounds.DEFAULT) {
if (offsetAsPageNum) {
page = new Offset(), Limit(), rowBoundsWithCount);
} else {
page = new Page(new int[]{Offset(), Limit()}, rowBoundsWithCount);
//offsetAsPageNum=false的时候,由于PageNum问题,不能使⽤reasonable,这⾥会强制为false
page.setReasonable(false);
}
if(rowBounds instanceof PageRowBounds){
PageRowBounds pageRowBounds = (PageRowBounds)rowBounds;
page.Count() == null || Count());
}
//如果pagehelper.supportMethodsArguments 设置为true,也就是⽀持接⼝参数来传递分页参数
} else if(supportMethodsArguments){
try {
page = PageFromObject(parameterObject, false);
} catch (Exception e) {
return null;
}
}
if(page == null){
return null;
}
PageHelper.setLocalPage(page);
}
从上⾯代码可以看出 如果没有修改rowBounds,并且没有设置pagehelper.supportMethodsArguments 属性为true,是不会⾛分页的,也就是直接skip掉了。但是通常我们希望接⼝来传递分页参数,会把pagehelper.supportMethodsArguments设置为true。所以会⾛page = PageFromObject(parameterObject, false)流程。
public static <T> Page<T> getPageFromObject(Object params, boolean required) {
int pageNum;
int pageSize;
MetaObject paramsObject = null;
if (params == null) {
throw new PageException("⽆法获取分页查询参数!");
}
if (hasRequest && requestClass.Class())) {
try {
paramsObject = MetaObjectUtil.forObject(getParameterMap.invoke(params, new Object[]{})); } catch (Exception e) {
//忽略
}
} else {
paramsObject = MetaObjectUtil.forObject(params);
}
if (paramsObject == null) {
throw new PageException("分页查询参数处理失败!");
}
Object orderBy = getParamValue(paramsObject, "orderBy", false);
boolean hasOrderBy = false;
if (orderBy != null && String().length() > 0) {
hasOrderBy = true;
}
try {
Object _pageNum = getParamValue(paramsObject, "pageNum", required);
Object _pageSize = getParamValue(paramsObject, "pageSize", required);
if (_pageNum == null || _pageSize == null) {
if(hasOrderBy){
Page page = new Page();
page.String());
page.setOrderByOnly(true);
return page;
分页查询插件}
return null;
}
pageNum = Integer.parseInt(String.valueOf(_pageNum));
pageSize = Integer.parseInt(String.valueOf(_pageSize));
} catch (NumberFormatException e) {
throw new PageException("分页参数不是合法的数字类型!");
}
Page page = new Page(pageNum, pageSize);
/
/count查询
Object _count = getParamValue(paramsObject, "count", false);
if (_count != null) {
page.setCount(Boolean.valueOf(String.valueOf(_count)));
}
//排序
if (hasOrderBy) {
page.String());
}
//分页合理化
Object reasonable = getParamValue(paramsObject, "reasonable", false);
if (reasonable != null) {
page.setReasonable(Boolean.valueOf(String.valueOf(reasonable)));
}
//查询全部
Object pageSizeZero = getParamValue(paramsObject, "pageSizeZero", false);
if (pageSizeZero != null) {
page.setPageSizeZero(Boolean.valueOf(String.valueOf(pageSizeZero)));
}
return page;
}
从以上简单代码中我们可以发现,如果sql⼊参中存在 orderby或者同时存在pageNum 和pageSize那么page还是不等于null,即
skip!=true
跳过查总数据
回到PageInterceptor的intercept⽅法,skip = true⾛分页流程时会判断是否需要进⾏ count 查询
if (dialect.beforeCount(ms, parameter, rowBounds))
...
public boolean beforeCount(MappedStatement ms, Object parameterObject, RowBounds rowBounds) {
Page page = getLocalPage();
return !page.isOrderByOnly() && page.isCount();
}
当page不是只orderBy时并且page.isCount()为true时,需要进⾏count查询,那么简单破坏Page就能达到跳过count查总数据需求。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论