PageHelper 排序报错

问题重现

开发环境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



作者:Formaxcn
链接:https://www.jianshu.com/p/c5fa441f6066

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当你在导入PageHelper插件时遇到错误,可能有几种原因导致。以下是一些常见的问题和解决方法: 1. 依赖问题:请确保你在项目的pom.xml(如果是Maven项目)或者build.gradle(如果是Gradle项目)中正确添加了PageHelper的依赖。例如,在Maven项目中,你可以在dependencies标签中添加以下代码: ```xml <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>版本号</version> </dependency> ``` 请确保版本号与你使用的PageHelper版本一致。 2. 配置问题:在使用PageHelper之前,你需要在你的项目中配置PageHelper。通常,你需要在配置文件(如application.properties或application.yml)中添加相关配置。例如,在Spring Boot项目中,你可以在配置文件中添加以下代码: ```yaml pagehelper: helper-dialect: 数据库类型 reasonable: true support-methods-arguments: true params: count=countSql ``` 其中,数据库类型可以是"mysql"、"oracle"等,根据你使用的数据库类型进行配置。 3. 导入问题:请确保你正确导入了PageHelper的相关类和方法。通常,你需要在你的代码中导入PageHelper类,并使用其中的方法来实现分页功能。例如,在Java代码中,你可以使用以下导入语句: ```java import com.github.pagehelper.PageHelper; ``` 然后,你可以使用PageHelper.startPage()方法来开启分页功能。 如果你仍然遇到问题,请提供更多的错误信息和代码片段,以便我能够更好地帮助你解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值