概述
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) {
if(ms.getId().endsWith(MSUtils.COUNT)){
throw new RuntimeException("在系统中发现了多个分页插件,请检查系统配置!");
}
//获取分页参数成功,则分页,获取失败,则跳过分页
Page page = pageParams.getPage(parameterObject, rowBounds);
if (page == null) {
return true;
} else {
//设置默认的 count 列
if(StringUtil.isEmpty(page.getCountColumn())){
page.setCountColumn(pageParams.getCountColumn());
}
autoDialect.initDelegateDialect(ms);
return false;
}
}
从skip方法可以看出,跳过分页的重点在pageParams.getPage。
//如果当前threadlocal中有page取当前threadlocal中的page
Page page = PageHelper.getLocalPage();
if (page == null) {
// 不人为修改时rowBounds = RowBounds.DEFAULT
if (rowBounds != RowBounds.DEFAULT) {
if (offsetAsPageNum) {
page = new Page(rowBounds.getOffset(), rowBounds.getLimit(), rowBoundsWithCount);
} else {
page = new Page(new int[]{rowBounds.getOffset(), rowBounds.getLimit()}, rowBoundsWithCount);
//offsetAsPageNum=false的时候,由于PageNum问题,不能使用reasonable,这里会强制为false
page.setReasonable(false);
}
if(rowBounds instanceof PageRowBounds){
PageRowBounds pageRowBounds = (PageRowBounds)rowBounds;
page.setCount(pageRowBounds.getCount() == null || pageRowBounds.getCount());
}
//如果pagehelper.supportMethodsArguments 设置为true,也就是支持接口参数来传递分页参数
} else if(supportMethodsArguments){
try {
page = PageObjectUtil.getPageFromObject(parameterObject, false);
} catch (Exception e) {
return null;
}
}
if(page == null){
return null;
}
PageHelper.setLocalPage(page);
}
从上面代码可以看出 如果没有修改rowBounds,并且没有设置pagehelper.supportMethodsArguments 属性为true,是不会走分页的,也就是直接skip掉了。但是通常我们希望接口来传递分页参数,会把pagehelper.supportMethodsArguments设置为true。所以会走page = PageObjectUtil.getPageFromObject(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.isAssignableFrom(params.getClass())) {
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 && orderBy.toString().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.setOrderBy(orderBy.toString());
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.setOrderBy(orderBy.toString());
}
//分页合理化
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查总数据需求。
最后
以上就是舒心吐司为你收集整理的使用com.github.pagehelper插件分页、count分析的全部内容,希望文章能够帮你解决使用com.github.pagehelper插件分页、count分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复