文章目录

1. 复现错误2. 分析错误3. 解决错误4. 解决该错误的其他方法4.1 方法说明4.2 建表规范

5. 补充说明

本文不仅帮你解决错误,还帮你分析错误的原因

1. 复现错误

今天写好创建数据源的接口,并启动项目后,通过Knife4j调用单接口,但保出如下图错误:

于是,查看后端输出详细的错误信息,如下所示:

org.springframework.jdbc.UncategorizedSQLException:

### Error querying database. Cause: java.sql.SQLException: sql injection violation, dbType mysql, , druid-version 1.2.11, syntax error: not supported.pos 86, line 1, column 79, token IDENTIFIER deleted : SELECT * FROM `datasource` where datasource_key = ? and id <> ? and app_id = ? deleted = 0 LIMIT 1

### The error may exist in com/xxx/mapper/DatasourceMapper.java (best guess)

### The error may involve com.xxx.mapper.DatasourceMapper.getByDatasourceKeyAndId

### The error occurred while executing a query

### SQL: SELECT * FROM `datasource` where datasource_key = ? and id <> ? and app_id = ? deleted = 0 LIMIT 1

### Cause: java.sql.SQLException: sql injection violation, dbType mysql, , druid-version 1.2.11, syntax error: not supported.pos 86, line 1, column 79, token IDENTIFIER deleted : SELECT * FROM `datasource` where datasource_key = ? and id <> ? and app_id = ? deleted = 0 LIMIT 1

; uncategorized SQLException; SQL state [null]; error code [0]; sql injection violation, dbType mysql, , druid-version 1.2.11, syntax error: not supported.pos 86, line 1, column 79, token IDENTIFIER deleted : SELECT * FROM `datasource` where datasource_key = ? and id <> ? and app_id = ? deleted = 0 LIMIT 1; nested exception is java.sql.SQLException: sql injection violation, dbType mysql, , druid-version 1.2.11, syntax error: not supported.pos 86, line 1, column 79, token IDENTIFIER deleted : SELECT * FROM `datasource` where datasource_key = ? and id <> ? and app_id = ? deleted = 0 LIMIT 1

at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:92)

at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441)

at com.sun.proxy.$Proxy160.selectOne(Unknown Source)

at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:160)

at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:89)

at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)

at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)

at com.sun.proxy.$Proxy166.getByDatasourceKeyAndId(Unknown Source)

at com.xxx.service.DatasourceService.modifyDatasource(DatasourceService.java:104)

at com.xxx.service.DatasourceService$$FastClassBySpringCGLIB$$ae4aeefa.invoke()

at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)

at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)

at com.xxx.service.DatasourceService$$EnhancerBySpringCGLIB$$1c1c65fc.modifyDatasource()

at com.xxx.controller.DatasourceController.modifyDatasource(DatasourceController.java:96)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)

at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)

at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)

at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)

at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at com.github.xiaoymin.knife4j.spring.filter.SecurityBasicAuthFilter.doFilter(SecurityBasicAuthFilter.java:87)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:114)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

.....

由于篇幅有限,没有粘贴出全部的错误信息。

2. 分析错误

由于错误信息很多,我们只需要关注Cause: java.sql.SQLException: sql injection violation, dbType mysql, , druid-version 1.2.11, syntax error: not supported.pos 86, line 1, column 79, token IDENTIFIER deleted这句话即可。

正赶上最近ChatGPT比较火,我们可以借助它来分析我的错误,如下图所示:

ChatGPT说我的错误由于SQL注入导致的,使用了mysql不支持的语法。

于是继续分析上述的错误信息,查找到DatasourceMapper类中的getByDatasourceKeyAndId方法,该方法如下代码所示:

@Select(

"SELECT "

+ " * "

+ "FROM "

+ " `datasource` "

+ "WHERE "

+ " datasource_key = #{datasourceKey} and id <> #{id} and app_id = #{appId} deleted = 0 LIMIT 1")

Datasource getByDatasourceKeyAndId(String datasourceKey, Long id, Long appId);

经过反复检查上述代码,却没有发现任何问题,只能通过如下断点的方式分析:

通过断点发现,在app_id = ? deleted = 0没有and符号,即app_id = #{appId} deleted = 0没有and符号。

3. 解决错误

既然在app_id = #{appId} deleted = 0没有and符号,在其加上and符号即可,如下代码所示:

@Select(

"SELECT "

+ " * "

+ "FROM "

+ " `datasource` "

+ "where "

+ " datasource_key = #{datasourceKey} and id <> #{id} and app_id = #{appId} and deleted = 0 LIMIT 1")

Datasource getByDatasourceKeyAndId(String datasourceKey, Long id, Long appId);

重新启动项目,再次使用Knife4j测试该接口,即可成功访问,如下图所示:

4. 解决该错误的其他方法

\

4.1 方法说明

我的错误是由于缺少关键字(and)导致的。

如果我的错误解决方法,无法解决你的错误,可以参考如下的解决方法

一般情况下,该错误是因为表字段和关键字冲突,这个问题解决后多数情况都正常了。

若开发工具不显示SQL的关键字,导致不方便区分的话,我知道如下三种解决办法:

可以把感觉不对劲的表名和字段名都用 ` ` 给注上,如 `status`。 给冲突的字段或表名起别名。 还可以在oracle中使用双引号" ",将冲突的列名括起来。

4.2 建表规范

为了避免表字段和关键字冲突,在数据库最初建表时,需要有意识的避免字段冲突问题,下面是网上找的建表命名规范:

采用系统名+_+t_+模块名+_+表义名格式构成。 若数据库中只含有单个模块,命名可采用系统名+t_+表义名格式构成。 整个表名的长度不要超过30个字符。 系统名、模块名均采用小写字符。 模块名或表义名均以其英文单词命名,且字符间不加分割符:

表义名中单词的首字符大写,其它字符小写。 多个单词间也不加任何分割符,单词全部采用单数形式。 表别名命名规则:

取表义名的前3个字符加最后一个字符。 如果存在冲突,适当增加字符(如取表义名的前4个字符加最后一个字符等)。 关联表命名为Re_表A_表B:

Re是Relative的缩写 表A和表B均采用其表义名或缩写形式。

这样会避免与关键字冲突,将麻烦降到最低。

5. 补充说明

如果你对Knife4j感兴趣,可以参考博文:全网最全的Knife4j swaggerj介绍

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: