PageHelper 问题定位

问题简述:
问题现象:select * from table order by field ${orderBy} → select * from table order by ${orderBy}

问题原因:入参字段 orderBy 被 PageHelper 作为 排序 ,重写了 原 SQL 语句的 排序

解决方案与源码:

1、(推荐)通过 pagehelper.support-methods-arguments: false 禁止PageHelper使用入参进行分页排序等sql重写

2、(临时)修改入参字段,区别于 PageHelper 所使用的字段

源码追踪:
1、参数配置的代码方法,重点见 16 行 【com.github.pagehelper.page.PageParams.getPage(Object parameterObject, RowBounds rowBounds)】

/**
 * 获取分页参数
 *
 * @param parameterObject
 * @param rowBounds
 * @return
 */
public Page getPage(Object parameterObject, RowBounds rowBounds) {
    Page page = PageHelper.getLocalPage();
    if (page == null) {
        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());
            }
        } else if(supportMethodsArguments){  //pagehelper.support-methods-arguments: false 配置
            try {
                page = PageObjectUtil.getPageFromObject(parameterObject, false);
            } catch (Exception e) {
                return null;
            }
        }
        if(page == null){
            return null;
        }
        PageHelper.setLocalPage(page);
    }
    //分页合理化
    if (page.getReasonable() == null) {
        page.setReasonable(reasonable);
    }
    //当设置为true的时候,如果pagesize设置为0(或RowBounds的limit=0),就不执行分页,返回全部结果
    if (page.getPageSizeZero() == null) {
        page.setPageSizeZero(pageSizeZero);
    }
    return page;
}

2、临时修改入参字段命名的方法,见26行 【com.github.pagehelper.util.PageObjectUtil.getPageFromObject(Object params, boolean required)】

/**
 * 对象中获取分页参数
 *
 * @param params
 * @return
 */
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;
}

重写OrderBy SQL 【com.github.pagehelper.parser.OrderByParser.converToOrderBySql(String sql, String orderBy)】

/**
 * convert to order by sql
 *
 * @param sql
 * @param orderBy
 * @return
 */
public static String converToOrderBySql(String sql, String orderBy) {
    //解析SQL
    Statement stmt = null;
    try {
        stmt = CCJSqlParserUtil.parse(sql);
        Select select = (Select) stmt;
        SelectBody selectBody = select.getSelectBody();
        //处理body-去最外层order by
        List<OrderByElement> orderByElements = extraOrderBy(selectBody);
        String defaultOrderBy = PlainSelect.orderByToString(orderByElements);
        if (defaultOrderBy.indexOf('?') != -1) {
            throw new RuntimeException("原SQL[" + sql + "]中的order by包含参数,因此不能使用OrderBy插件进行修改!");
        }
        //新的sql
        sql = select.toString();
    } catch (Throwable e) {
        e.printStackTrace();
    }
    return sql + " order by " + orderBy;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值