其异常信息如下
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正常使用。