项目场景:
在开发或运行使用 MyBatis-Plus 分页功能的项目时,控制台突然抛出以下异常:
[http-nio-8082-exec-7] c.b.m.e.p.i.PaginationInnerInterceptor failed to concat orderBy from IPage, exception:
java.util.concurrent.ExecutionException: net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "group" "GROUP"
at line 18, column 9.
Was expecting:
<EOF>
问题排查
该异常直接指向 SQL 语法错误,且与分页时的 ORDER BY 拼接有关。通常需要检查:
- 分页查询的 Page 对象是否设置了正确的排序字段?
- 被分页的 SQL 语句本身语法是否正确?特别是 ORDER BY 子句附近。
根本原因分析
经过汗流浃背的排查,发现问题并非出现在 Page 对象的排序设置上,也不是 ORDER BY 子句本身的语法错误。
真正的罪魁祸首是:MyBatis-Plus 映射文件 (XXXMapper.xml) 中的 SQL 语句注释方式!
场景描述:
在一个较长的、包含 GROUP BY 子句的 SQL 语句中间,使用 XML 注释 (< !-- … -->) 注释掉了一段代码。
被注释掉的代码块恰好位于 GROUP BY 关键字之前或之中。
例如,原始有效的 SQL 结构可能是:
SELECT ... FROM ... WHERE ...
-- 这里被注释掉了一大段逻辑 (例如 JOIN 或 WHERE 条件)
GROUP BY ... -- 第18行附近
ORDER BY ...
在本案例中,注释导致了 GROUP BY 关键字直接暴露在了 SQL 语句中一个语法解析器无法理解的位置(例如,紧跟在某个未结束的表达式或子句之后,或者出现在 ORDER BY 应该出现的位置之前)。这使得 MyBatis-Plus 的分页拦截器在尝试追加 ORDER BY 时,整个 SQL 的语法结构已经因为之前的注释而被破坏,最终引发了 jsqlparser 在解析拼接后的 SQL 时遇到的 GROUP 关键字异常。
错误示例 (注释导致结构破坏):
<select id="selectComplexData" resultType="...">
SELECT col1, col2, SUM(col3) AS total
FROM main_table
<!-- 原计划注释掉这个JOIN和相关条件,但注释位置不当 -->
<!--
JOIN other_table ON main_table.id = other_table.ref_id
WHERE other_table.status = 'ACTIVE'
AND some_condition = true
-->
GROUP BY col1, col2 -- 第18行:解析器期望前面有完整的FROM/JOIN/WHERE结构,但注释导致结构缺失
ORDER BY col1 ASC
</select>
解决方案:
彻底删除无用代码: 将 XML 映射文件中被注释掉的、不再需要的 SQL 片段完全删除。这是最安全、最推荐的做法,避免未来维护者踩坑。
删除掉 XML 文件中导致 SQL 语法结构破坏的注释代码块后(或者将注释的sql挪到最后),SQL 语句恢复完整的、正确的语法结构。MyBatis-Plus 的分页拦截器 (PaginationInnerInterceptor) 能够正常地在原始 SQL 后追加 ORDER BY 子句,jsqlparser 也能正确解析拼接后的完整 SQL,异常消失,分页功能恢复正常。
经验总结:
- 警惕 XML 注释对 SQL 结构的影响: MyBatis XML 中的注释 (< !-- … -->)会物理移除注释内容。如果注释掉的是连接 SQL 关键部分的代码,极易导致剩余 SQL语法错误。这种错误往往比较隐蔽,因为注释掉的代码本身不执行,但会影响剩下的“可见”代码的结构。
- 清理无用代码: 长期不用的、注释掉的代码应及时清理,减少干扰和潜在风险。
- 理解分页拦截器的工作机制: MyBatis-Plus 的分页是通过拦截器修改原始 SQL 实现的。任何导致原始 SQL语法结构异常的因素(如本案例的注释破坏),都可能在拦截器拼接 ORDER BY 或 LIMIT 时暴露出来。