java PageHelper 会自动对orderBy关键字进行处理

1.查询对象

public class child{
    public String name;
    public String orderBy;
}

2.设置值

child ch = new Child();
ch.setOrderBy(" test");
ch.setName("123");

3.实际生成的sql

select  * from child where name = "123" test

4.实现是用mybatils的拦截器,可看 PageHelper 的 SqlUtil类,实现代码如下(第20行代码处理orderBy关键字)

public static <T> Page<T> getPageFromObject(Object params) {
    int pageNum;
    int pageSize;
    MetaObject paramsObject = null;
    if (params == null) {
        throw new NullPointerException("无法获取分页查询参数!");
    }
    if (hasRequest && requestClass.isAssignableFrom(params.getClass())) {
        try {
            paramsObject = SystemMetaObject.forObject(getParameterMap.invoke(params, new Object[]{}));
        } catch (Exception e) {
            //忽略
        }
    } else {
        paramsObject = SystemMetaObject.forObject(params);
    }
    if (paramsObject == null) {
        throw new NullPointerException("分页查询参数处理失败!");
    }
    Object orderBy = getParamValue(paramsObject, "orderBy", false);
    boolean hasOrderBy = false;
    if (orderBy != null && orderBy.toString().length() > 0) {
        hasOrderBy = true;
    }
    try {
        Object _pageNum = getParamValue(paramsObject, "pageNum", hasOrderBy ? false : true);
        Object _pageSize = getParamValue(paramsObject, "pageSize", hasOrderBy ? false : true);
        if (_pageNum == null || _pageSize == null) {
            Page page = new Page();
            page.setOrderBy(orderBy.toString());
            page.setOrderByOnly(true);
            return page;
        }
        pageNum = Integer.parseInt(String.valueOf(_pageNum));
        pageSize = Integer.parseInt(String.valueOf(_pageSize));
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("分页参数不是合法的数字类型!");
    }
    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;
}

### PageHelper 中 `orderby` 与 XML 文件中定义的 `orderby` 冲突分析 在 MyBatis 的分页插件 PageHelper 中,当使用动态 SQL 或者通过 Java 代码设置 `orderBy` 参数时,可能会遇到与 XML 映射文件中预定义的 `ORDER BY` 存在冲突的情况。这种冲突通常发生在 PageHelper 插入的 `ORDER BY` 和 XML 定义中的 `ORDER BY` 同时存在并相互干扰的情况下。 #### 解决方案一:禁用 PageHelper 自动追加的 `ORDER BY` 可以通过配置参数来控制 PageHelper 是否自动附加 `ORDER BY` 到查询语句中。如果希望完全由 XML 文件决定排序逻辑,则可以在调用分页方法前关闭 PageHelper 的默认行为: ```java PageHelper.startPage(pageNum, pageSize).setOrderBy(null); ``` 上述代码会清除 PageHelper 默认的 `ORDER BY` 设置[^1],从而避免其与 XML 文件中的排序规则发生冲突。 #### 解决方案二:调整优先级——仅保留一种来源的 `ORDER BY` 另一种方式是在业务层明确指定排序字段,并确保 XML 文件不包含硬编码的 `ORDER BY` 部分。例如,在 Mapper 接口中可以这样实现: ```xml <select id="selectUsers" resultType="User"> SELECT * FROM users <if test="_parameter != null and _parameter.orderByClause != null"> ORDER BY ${_parameter.orderByClause} </if> </select> ``` 此片段允许外部传参覆盖内部固定的排序条件[^2]。因此,即使 PageHelper 提供了自己的 `ORDER BY` 字符串,也不会被 XML 文件内的静态部分所影响。 #### 方案三:自定义拦截器处理重复 `ORDER BY` 对于更复杂的场景,可能需要编写自定义拦截器以过滤掉多余的 `ORDER BY` 关键字。具体做法如下所示: ```java @Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) }) public class CustomOrderInterceptor implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { BoundSql boundSql = ((MappedStatement)invocation.getArgs()[0]).getBoundSql(invocation.getArgs()[1]); String sql = boundSql.getSql(); // 去除多余 order by Pattern pattern = Pattern.compile("(?i)(order\\s*by)[^,]*"); Matcher matcher = pattern.matcher(sql); while (matcher.find()) { int startIdx = matcher.start(); int endIdx = matcher.end(); if (!sql.substring(endIdx).trim().isEmpty() && !Character.isWhitespace(sql.charAt(endIdx))) { continue; } sql = sql.substring(0, startIdx) + sql.substring(endIdx); } Field field = BoundSql.class.getDeclaredField("sql"); field.setAccessible(true); field.set(boundSql, sql); return invocation.proceed(); } public Object plugin(Object target){ return Plugin.wrap(target,this); } public void setProperties(Properties properties){} } ``` 以上代码展示了如何创建一个简单的 MyBatis 拦截器用于移除不必要的 `ORDER BY` 条款[^3]。 ### 注意事项 - 如果项目中有大量已存在的 SQL 查询依赖于固定写法的 `ORDER BY` ,那么修改这些地方的成本较高; - 使用 `${}` 占位符代替 `#{}` 可能带来潜在的安全隐患(SQL 注入风险),需谨慎对待输入验证环节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值