mybatisplus查询分页并且排序报错解决方法,适用于自定义sql和sqlserver

本文探讨了在MybatisPlus中使用自定义SQL进行分页排序时遇到的问题,重点在于`apply`关键字导致的SQL解析错误。通过源码分析和实例调试,揭示了如何避免此问题并正确添加排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mybatisplus的分页查询很好用,当然大部分人分页后查询也没有问题,因为使用mybatis的构造器分页并且排序不会出现各种各样的问题,sql自动的帮你生成了。
但是当我们需要查询多张表时或者查询sql复杂的情况下,我们或许需要自己写sql,然后调用Page来实现分页。
唔姆,到这里都没有问题。

 Page<持久层实体> queryPage =
        queryRepository.selectPageVo(new Page<持久层实体>(当前页, 页长度), 查询条件);

正常流程下,mybatis会进行总数,页数等等的查询,返回返回total,size,current和record。
问题来了,进行count查询的时候,mybatis会在我们的自定义sql外嵌套total查询。如果我们在自定义sql里写了排序,order by的话,sqlserver就一定会报错,因为相当于是在子查询里排序了种种啥的。
然而大伙几乎都没有遇到这种情况,大部分都是使用构造器进行简单的sql查询分页排序。
为了解决需求,只有看看源码有没有提供了。幸运的是,Page源码里有关于排序的方法,addOrder,赶紧用起来试试,这一次,我们sql里就不添加order by语句了,让分页自己去排序。

Page<持久层实体> queryPage =
        queryRepository.selectPageVo(new Page<持久层实体>(当前页, 页长度)
        .addOrder(OrderItem.desc(排序字段)), 查询条件);

于是我们看看查询的结果,嗯?为什么依旧没有排序?查看日志,粗大问题了惹。

failed to concat orderBy from IPage, exception=null

这是什么原因?没办法继续查看底层实现。手动跟进debug看到了原由

final public Statement Statement() throws ParseException {/*@bgen(jjtree) Statement */
  SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtn000.jjtSetFirstToken(getToken(1));Statement stm = null;
    try {
      try {
        stm = SingleStatement();
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case ST_SEMICOLON:{
          jj_consume_token(ST_SEMICOLON);
          break;
          }
        default:
          jj_la1[0] = jj_gen;
          ;
        }
        ......

在这里报错了!
原来mybatis会调用CCJSqlParser去解析,那么为什么会解析失败啊?
这里我们直接调用CCJSqlParserUtil去看看我们的sql为什么会这样!!

String sql = "你的sql";
    try {
      CCJSqlParserUtil.parse(sql);
    } catch (JSQLParserException e) {
      e.printStackTrace();
    }

通过一遍一遍的修改sql最后终于把问题定位了!!
关键字!

net.sf.jsqlparser.JSQLParserException: Encountered unexpected token: "apply" "APPLY"
    at line 1, column 15.

Was expecting one of:

    "("
    "ACTION"
    "ANY"
    "BYTE"
    "CASCADE"
    "CAST"
    "CHANGE"
    "CHAR"
    "CHARACTER"
    "COLUMN"
    "COLUMNS"
    "COMMENT"
    "COMMIT"
    "CREATE"
    "CYCLE"
    "DESC"
    "DESCRIBE"
    "DISABLE"
    "DIV"
    "DO"
    "DOUBLE"
    "DUPLICATE"
    "ENABLE"
    "END"
    "EXCLUDE"
    "EXTRACT"
    "FALSE"
    "FIRST"
    "FN"
    "FOLLOWING"
    "FORMAT"
    "GROUP"
    "IF"
    "INDEX"
    "INSERT"
    "INTERVAL"
    "ISNULL"
    "KEY"
    "LAST"
    "LATERAL"
    "LEFT"
    "LIMIT"
    "MATERIALIZED"
    "NEXTVAL"
    "NO"
    "NOLOCK"
    "NULLS"
    "OF"
    "OFFSET"
    "ON"
    "OPEN"
    "OPTIMIZE"
    "ORDER"
    "OVER"
    "PARTITION"
    "PATH"
    "PERCENT"
    "PRECISION"
    "PRIMARY"
    "PRIOR"
    "PROCEDURE"
    "PUBLIC"
    "RANGE"
    "READ"
    "REPLACE"
    "RIGHT"
    "ROW"
    "ROWS"
    "SCHEMA"
    "SEPARATOR"
    "SEQUENCE"
    "SESSION"
    "SET"
    "SIBLINGS"
    "SIZE"
    "START"
    "TABLE"
    "TABLES"
    "TEMP"
    "TEMPORARY"
    "TO"
    "TOP"
    "TRUE"
    "TRUNCATE"
    "TYPE"
    "UNSIGNED"
    "VALIDATE"
    "VALUE"
    "VALUES"
    "VIEW"
    "XML"
    "ZONE"
    "{"
    <K_DATETIMELITERAL>
    <K_DATE_LITERAL>
    <S_IDENTIFIER>
    <S_QUOTED_IDENTIFIER>

万万没想到,因为我们的sql里有apply,居然就一直无法解析!!最坑的是,报错里并没有嗦apply有问题,我一直以为是apply周围有什么字段啥的出问题了。于是我们把sql改一下。

 String sql = "select * from \"apply\"";
    try {
      CCJSqlParserUtil.parse(sql);
    } catch (JSQLParserException e) {
      e.printStackTrace();
    }
Process finished with exit code 0

好了,并没有报错。
于是我们把sql里关键字全部加长""双引号吧,现在sqlserver里跑一下,看看能否识别,再修改自定义sql,在分页的时候加上addOrder排序。
完美解决!
好了,大坑踩完了。GitHub里的issue也有人遇到了同样的问题,建议大家多看看多读读,多阅读源码看看底层

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值