美文网首页代码异常
PageHelper 排序踩坑记录

PageHelper 排序踩坑记录

作者: Formaxcn | 来源:发表于2019-01-24 16:44 被阅读0次

问题重现

开发环境Spring Boot + Mysql + mybatis+ pagehelper

开发中碰到莫名其妙的错误, 一个普通的分页查询, 莫名抛出错误

Cause: com.github.pagehelper.PageException: 处理排序失败: net.sf.jsqlparser.JSQLParserException
...
Caused by: com.github.pagehelper.PageException: 处理排序失败: net.sf.jsqlparser.JSQLParserException
...
Caused by: net.sf.jsqlparser.JSQLParserException: null
...
Caused by: net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "?" "?"
    at line 10, column 50.
Was expecting one of:

    "&"
    "."
    "::"
    ";"
    "<<"
    ">>"
    "AND"
    "CONNECT"
    "ESCAPE"
    "EXCEPT"
    "FOR"
    "GROUP"
    "HAVING"
    "INTERSECT"
    "MINUS"
    "ORDER"
    "START"
    "UNION"
    "^"
    "|"
    <EOF>

经过不同重试, 发现在模糊查询的条件有值且传入了排序字段, 错误会稳定重现, 遂查找相关代码(代码有所简化)分析:
pom.xml

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.9</version>        
</dependency>

xxxServiceImpl.java

@Override
public PagerVo<Vo> list(Form form){
    PageHelper.startPage(form.getPageNum(),
                        form.getPageSize(),
                        form.getOrderByString());
    List<model> lists=xxxMapper.list(form);
    PagerVo<Model> resultVo = new PagerVo<>(lists,
                                            new PageInfo(lists).getTotal());
    return resultVo;
}

xxxMapper.xml

<select id="list" resultMap="insuranceOrderListVO">
    select xxx,xxx,xxx
    from table1 a
    left join table2 b on a.xxx=b.id
    WHERE 1=1
    <if test= "condition1 != 0">
        AND a.condition=#{condition1}
    </if>
    <if test= "condition2!= null">
        AND b.condition like "%"#{condition2}"%"
    </if>
</select>

问题分析

注意到最开始报错, 是SQL不标准, 报错的包名为net.sf.jsqlparser, 是一个处理SQL的工具包, 具体错误为传入的sql中间存在其不能处理的字符, 遂开始检查具体的sql写法.
此时聚焦到 like 的条件拼接, "%"#{condition2}"%", 注意到此写法并非标准的sql写法, 猜测为mybatis对其进行了预处理, 此预处理可能与分页插件所用的SQL处理冲突, 为了验证猜想, 将其对应的sql语句 "%"#{condition2}"%" 更换一种写法:concat("%",#{condition2},"%"), 并在日志中加入其最终执行进行调试.
修改前-1: 传入"%"#{condition2}"%"+无排序字段(可以顺利执行)

select count(0) from 
    (select xxx,xxx,xxx
    from table1 a
    left join table2 b on a.xxx=b.id
    WHERE 1=1 
    AND b.condition like "%"?"%")
tmp_count 

修改前2: 传入"%"#{condition2}"%"+有排序字段(抛出错误)

select count(0) from 
    (select xxx,xxx,xxx
    from table1 a
    left join table2 b on a.xxx=b.id
    WHERE 1=1 
    AND b.condition like "%"?"%")
tmp_count 

修改前-3: 不传入"%"#{condition2}"%"+有排序字段(可以顺利执行)

SELECT count(0) 
from table1 a
left join table2 b on a.xxx=b.id
WHERE 1=1

修改后: concat("%",#{condition2},"%")+传入排序字段

SELECT count(0) 
from table1 a
left join table2 b on a.xxx=b.id
WHERE 1=1     
AND b.condition like concat("%", ?, "%")

比较修改前-2和修改前-3的执行sql, 发现在pagehelper计算总数的时候, 的确对传入的SQL进行了优化, 在计数sql执行时, 移除了不必要的返回字段列, 缩短了sql语句的长度, 当其解析sql语句结构失败时, 会将传入的整个sql语句当成普通sql语句处理;
比较修改前-1和修改前-2的执行sql, 当传入了排序字段时, 处理排序字段时, 其使用的SQL解析工具jsqlparser不支持含有预处理的sql语句, 导致了最终执行结果抛错.

解决方案

条件参数使用like时不要使用"%"#{condition2}"%"此种可能会导致预处理的写法, 可能由于不是标准的SQL语句导致其他处理方法抛出错误, 在mapper.xml中尽量使用兼容的SQL语句.

参考

https://blog.csdn.net/weixin_36146275/article/details/79355544

相关文章

  • PageHelper 排序踩坑记录

    问题重现 开发环境Spring Boot + Mysql + mybatis+ pagehelper 开发中碰到莫...

  • pageHelper踩坑记录

    pageHelper:好处就是使用简单,自动帮忙进行物理分割查询 断点截图 表中有4条数据,mapper是查询所有...

  • 算法踩坑6-二叉搜索树排序

    背景 接上面五篇文章算法踩坑-快速排序 算法踩坑2-插入排序 算法踩坑3-堆排序 算法踩坑4-冒泡排序 ...

  • 踩坑合集

    1、pagehelper 循环引用问题 解决方法: 方法一 方法二Pagehelper踩坑笔记[https://b...

  • 算法踩坑5-归并排序

    背景 接上面四篇文章算法踩坑-快速排序 算法踩坑2-插入排序 算法踩坑3-堆排序 算法踩坑4-冒泡排序 来...

  • 算法踩坑4-冒泡排序

    背景 接上面三篇文章算法踩坑-快速排序 算法踩坑2-插入排序 算法踩坑3-堆排序 来继续聊聊最近我写的一些算...

  • Pagehelper使用踩坑

    问题发现PageHelper有时候有效果,有时候没有效果我在项目中查了好久,后来在网上也进行了搜索,并发现了其中的...

  • PageHelper失效踩坑

    常见的pageHelper失效,一般由编写失误导致,根据源码指出pageHelper.startPage()方法必...

  • JavaScript踩过的坑

    开一篇记录踩过的坑...... Array.sort() 数组排序 Array.prototype.sort()有...

  • 分页插件PageHelper踩坑

    日常踩坑 测试说这个分页总条数total不对,总是等于传入的pageSize大小,一脸懵逼,看下库里确实不止这些数...

网友评论

    本文标题:PageHelper 排序踩坑记录

    本文链接:https://www.haomeiwen.com/subject/rtkujqtx.html