Mybatis-plus解析sql发生异常:net.sf.jsqlparser.JSQLParserException
作者:mmseoamin日期:2023-12-25

问题描述

在使用mybatis-plus的过程中,有一个jsonb字段使用了jsonb_exists_any (field_name, text[])作为where条件查询,执行sql如下:

SELECT * FROM table_name 

WHERE  jsonb_exists_any (field_name, ARRAY['110544709344', '12564892357'])

上面的sql在navicat中执行正常,所以sql没有问题,但是在mybatis-plus的xml文件中使用就会报错,异常信息如下:

Caused by: net.sf.jsqlparser.JSQLParserException: Encountered unexpected token: "(" "("
    at line 4, column 33.
Was expecting one of:
    "&"
    "&&"
    "::"
    ";"
    "<<"
    ">>"
    "AND"
    "COLLATE"
    "CONNECT"
    "EXCEPT"
    "FOR"
    "GROUP"
    "HAVING"
    "INTERSECT"
    "MINUS"
    "OR"
    "ORDER"
    "START"
    "UNION"
    "["
    "^"
    "|"
    
	at net.sf.jsqlparser.parser.CCJSqlParserUtil.parseStatements(CCJSqlParserUtil.java:188) ~[jsqlparser-4.0.1-SNAPSHOT.jar:na]
	at net.sf.jsqlparser.parser.CCJSqlParserUtil.parseStatements(CCJSqlParserUtil.java:176) ~[jsqlparser-4.0.1-SNAPSHOT.jar:na]
	at com.baomidou.mybatisplus.core.parser.AbstractJsqlParser.parser(AbstractJsqlParser.java:62) ~[mybatis-plus-core-3.4.2.jar:3.4.2]
	... 139 common frames omitted

解决方案

方案1:在网上看了很多解决方式,说是因为MyBatis_Plus框架中,有多租户的功能(也就是通过sql拦截器注入租户信息),MP会进行数据权限的过滤导致的,可以使用下面的注解(+配置)解决:

// Mybatis-plus 3.4.x以前的的版本
@SqlParser(filter = true)
// 如果Mybatis-plus版本是3.1.1以上的,直接添加@SqlParser注解即可,但如果是3.1.1以下版本,还需要在资源文件添加如下配置:
# 开启 SQL 解析缓存注解生效
mybatis-plus: 
    global-config: 
        sql-parser-cache: true
// Mybatis-plus 3.4.x之后的版本,@SqlParser已过期,可以直接使用下面的注解代替
@InterceptorIgnore(tenantLine = "true")

方案2: 由于我们的系统本身就需要多租户功能,所以无法通过上面的方式解决,在网上又找了下,看到了通过升级com.github.jsqlparser:jsqlparser sql解析器,解决依赖冲突的方案来解决:

https://blog.csdn.net/xiaozhang_man/article/details/127193780

最终方案: 由于不敢随便升级依赖包,怕引入新的问题,我最终的解决方案是不使用array函数,避开jsqlparser不支持某些关键字或函数,修改后的sql如下:

SELECT * FROM table_name

WHERE  jsonb_exists_any (field_name, '{110544709344, 12564892357}')

扩展知识:jsonb_exists_any只支持字符串数组(text[])的检索,不支持integer、bigint等数值类型,在构建json数据结构的时候需要注意下。