sql于navicat中能运行在mybatis中不能运行

本文详细介绍了在使用MyBatisPlus时遇到的一个SQL解析异常,该异常源于MyBatisPlus的SQL解析处理器在处理特定SQL语句时抛出。通过调试发现,问题在于`IN()`条件后跟`=0`导致解析错误。解决方法包括使用@SqlParser注解跳过解析或修改SQL语句,将`IN()=0`改为`NOT IN()`。最终选择了修改SQL语句的方法,成功解决了问题。
摘要由CSDN通过智能技术生成

其异常信息如下

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:

Error querying database. Cause: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Failed to process, please exclude the tableName or statementId.


在本条sql中,于navicat中是可以正常运行的,但是在mybatisplus中是不可以正常使用的

SELECT
	claim_key,
	claim_no,
	occur_time,
	amnt,
	b_name,
	city_branch_code,
	town_branch_code,
	cntr_no,
	opsn_name,
	opsn_id_no,
	rcpt_amnt,
	occur_result_code,
	accept_clerk_code,
	accept_branch_no,
	proc_clerk_no,
	proc_clerk_branch,
	chk_clerk_no,
	pol_code,
	claim_date,
	close_date,
	accept_channel,
	hospital_name,
	occur_1cls_code,
	lp_extracted 
FROM
	compensation_case 
WHERE
	stamp & gt;= DATE_FORMAT( "2021-02-08 00:00:00", 'yyyy-MM-dd %H:%m:%s' ) 
AND stamp & lt;= DATE_FORMAT( "2023-02-08 00:00:00", 'yyyy-MM-dd %H:%m:%s' ) 
AND lp_extracted = 0 
AND claim_proc_stat = 'E' 
AND pol_code IN ( 'DDD', 'DDE', '975' ) = 0

后经排查,有两个解决方案

1、使用注解 @SqlParser(filter = true) 就可以解决问题,其实现原理为略过 mybatis plus的SQL解析过滤,直接执行sql,这个效果跟在navicat执行sql的效果是一样的。

2、修改sql语句,将in () = 0 修改为 not in,这样子的话就可以在mybatis plus中就可以正常运行了。

其具体的出错原因还需要进行debug查询。


在debug的过程中,看到了mybatisplus的解析处理器中如下代码

public abstract class AbstractSqlParserHandler{
    /**
     * 拦截 SQL 解析执行
     */
    protected void sqlParser(MetaObject metaObject) {
        //
        // @SqlParser(filter = true) 跳过该方法解析
        if (SqlParserHelper.getSqlParserInfo(metaObject)) {
            return;
        }
        //
    }
}

可以看到如果加上了@SqlParser(filter = true)注解的话,就会跳过SQL解析。


在底层sql解析中,可以看到sql在where解析的时候,抛出了异常,根据特殊符号进行解析

net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "=" "="
    at line 33, column 51.

Was expecting one of:

    "&&"
    ";"
    "AND"
    "CONNECT"
    "EXCEPT"
    "FOR"
    "GROUP"
    "HAVING"
    "INTERSECT"
    "MINUS"
    "ORDER"
    "START"
    "UNION"
    <EOF>

特殊符号如下

"&&"
";"
"AND"
"CONNECT"
"EXCEPT"
"FOR"
"GROUP"
"HAVING"
"INTERSECT"
"MINUS"
"ORDER"
"START"
"UNION"

在解析sql的时候,对于如下sql是这么解析的

AND pol_code IN ( 'DDD', 'DDE', '975' ) = 0

根据IN解析之后,认为下面这条SQL

AND pol_code IN ( 'DDD', 'DDE', '975' )

解析完成之后是一个完整的条件语句了。那么这个条件语句它后面希望读取到的字符会期望是特殊符号

"&&"
";"
"AND"
"CONNECT"
"EXCEPT"
"FOR"
"GROUP"
"HAVING"
"INTERSECT"
"MINUS"
"ORDER"
"START"
"UNION"

但是由于本条SQL在

AND pol_code IN ( 'DDD', 'DDE', '975' )

之后提供的是 =

AND pol_code IN ( 'DDD', 'DDE', '975' ) = 0 

它不是mybatis plus所期望特俗字符中的其中一个,所以抛了异常,抛出异常的翻译如下:

net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "=" "="
    at line 33, column 51.

Was expecting one of:
    "&&"
    ";"
    "AND"
    "CONNECT"
    "EXCEPT"
    "FOR"
    "GROUP"
    "HAVING"
    "INTERSECT"
    "MINUS"
    "ORDER"
    "START"
    "UNION"
---------------------------------------------------------------------------------

在第 33 行第 51 列遇到意外标记:“=”“=”。期待以下之一:
    "&&"
    ";"
    "AND"
    "CONNECT"
    "EXCEPT"
    "FOR"
    "GROUP"
    "HAVING"
    "INTERSECT"
    "MINUS"
    "ORDER"
    "START"
    "UNION"

故解决该问题的办法有三种:

1、添加注解@SqlParser(filter = true),那么跳过mybatis的sql解析,直接就可以运行sql语句;

2、修改sql,将sql的 in () = 0 修改为 not in ();

3、修改源码。


综合考虑,选择第二种做法,将sql修改为如下

SELECT
	claim_key,
	claim_no,
	occur_time,
	amnt,
	b_name,
	city_branch_code,
	town_branch_code,
	cntr_no,
	opsn_name,
	opsn_id_no,
	rcpt_amnt,
	occur_result_code,
	accept_clerk_code,
	accept_branch_no,
	proc_clerk_no,
	proc_clerk_branch,
	chk_clerk_no,
	pol_code,
	claim_date,
	close_date,
	accept_channel,
	hospital_name,
	occur_1cls_code,
	lp_extracted 
FROM
	compensation_case 
WHERE
	stamp & gt;= DATE_FORMAT( "2021-02-08 00:00:00", 'yyyy-MM-dd %H:%m:%s' ) 
AND stamp & lt;= DATE_FORMAT( "2023-02-08 00:00:00", 'yyyy-MM-dd %H:%m:%s' ) 
AND lp_extracted = 0 
AND claim_proc_stat = 'E' 
AND pol_code NOT IN ( 'DDD', 'DDE', '975' )

修改之后重新运行,SQL正常使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值