sql于navicat中能运行在mybatis中不能运行的解决方案
作者:_0.78
其异常信息
如下:
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正常使用。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。