Mybatis-PageHelper 无法解析中括号的问题

nwo49xxi  于 2021-11-27  发布在  Java
关注(0)|答案(4)|浏览(376)
  • 我已在 issues 搜索类似问题,并且不存在相同的问题.

异常模板

使用环境

  • PageHelper 版本:pagehelper-spring-boot-starter:1.3.0
  • 数据库类型和版本: Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)
  • JDBC_URL: jdbc:jtds:sqlserver:///;useLOBs=false

SQL 解析错误

分页参数
page = PageHelper.startPage(pageNo, pageSize, count);
原 SQL

SELECT [ID] AS [ComsnCountID] FROM B_ComsnCount ;

期望的结果:

能解析成功

完整异常信息


### Error querying database.  Cause: java.sql.SQLException: 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。

### The error may exist in file [C:\IJProject\marketing\dao\target\classes\mapper\SellCommissionMapper.xml]

### The error may involve com.xkw.marketing.dao.mapper.SellCommissionMapper.queryCommissionCountList-Inline

### The error occurred while setting parameters

### Cause: java.sql.SQLException: 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。

; 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。; nested exception is java.sql.SQLException: 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。]

其他类型的错误

我看了源码,是在CountSqlParser的第180行,无法正常解析中括号,所以使用默认的getSimpleCountSql方法,但这个方法只是单纯的加一个count(0),没有去除 order by。

try {
            stmt = CCJSqlParserUtil.parse(sql);
        } catch (Throwable e) {
            //无法解析的用一般方法返回count语句
            return getSimpleCountSql(sql, name);
        }

但我使用这个SQL就能正常输出
SELECT ID AS ComsnCountID FROM B_ComsnCount ;
所以我觉得是因为新版本无法正常解析中括号导致的,我使用1.2.12版本就能正常解析

功能建议

建议优化 getSimpleCountSql 方法,或者排查CCJSqlParserUtil.parse(sql)中不能正常解析中括号的原因

bjp0bcyl

bjp0bcyl1#

1. 功能修改建议

com.github.pagehelper.parser.SqlServerParser

/**

* 转换为分页语句
* 
* @param sql
* @param offset
* @param limit
* @return
* /

public String convertToPageSql(String sql, Integer offset, Integer limit) {
    //解析SQL
    Statement stmt;
    try {
        stmt = CCJSqlParserUtil.parse(sql);
    } catch (Throwable e) {
        throw new PageException("不支持该SQL转换为分页查询!", e);
    }
    if (!(stmt instanceof Select)) {
        throw new PageException("分页语句必须是Select查询!");
    }
    //获取分页查询的select
    Select pageSelect = getPageSelect((Select) stmt);
    String pageSql = pageSelect.toString();
    //缓存移到外面了,所以不替换参数
    if (offset != null) {
        pageSql = pageSql.replace(START_ROW, String.valueOf(offset));
    }
    if (limit != null) {
        pageSql = pageSql.replace(PAGE_SIZE, String.valueOf(limit));
    }
    return pageSql;
}

订正方法:

/**

* Parses an sql statement while allowing via consumer to configure the used parser before.
* 
* For instance to activate SQLServer bracket quotation on could use:
* 
* {@code
* CCJSqlParserUtil.parse("select * from [mytable]", parser -> parser.withSquareBracketQuotation(true));
* }
* 
* @param sql
* @param consumer
* @return
* @throws JSQLParserException
* /

    public static Statement parse(String sql, Consumer<CCJSqlParser> consumer) throws JSQLParserException {
        CCJSqlParser parser = new CCJSqlParser(new StringProvider(sql));
        if (consumer != null) {
            consumer.accept(parser);
        }
        try {
            return parser.Statement();
        } catch (Exception ex) {
            throw new JSQLParserException(ex);
        }
    }
q0qdq0h2

q0qdq0h23#

等后续大版本升级jdk8时会解决上面的问题。

gdx19jrr

gdx19jrr4#

计划什么时候升级了, 项目还能赶得上吗 ?

相关问题