Invalid SQL statement or JDBC escape, terminating ''' not found.的解决办法。

简介:

项目中一直报如下的错误:

项目架构如下:Struts2.2.3 +Hibernate3.3 +Spirng 3.0 +Log4J-1.2.16+jtds-1.2.5.

 
  1. log4j:ERROR Failed to excute sql  
  2. java.sql.SQLException: Invalid SQL statement or JDBC escape, terminating ''' not found.  
  3.     at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:1155)  
  4.     at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:156)  
  5.     at net.sourceforge.jtds.jdbc.JtdsStatement.executeImpl(JtdsStatement.java:684)  
  6.     at net.sourceforge.jtds.jdbc.JtdsStatement.executeUpdate(JtdsStatement.java:1166)  
  7.     at net.sourceforge.jtds.jdbc.JtdsStatement.executeUpdate(JtdsStatement.java:1119)  
  8.     at org.apache.log4j.jdbc.JDBCAppender.execute(JDBCAppender.java:178)  
  9.     at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:250)  
  10.     at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:146)  
  11.     at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)  
  12.     at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)  
  13.     at org.apache.log4j.Category.callAppenders(Category.java:206)  
  14.     at org.apache.log4j.Category.forcedLog(Category.java:391)  
  15.     at org.apache.log4j.Category.log(Category.java:856)  
  16.     at org.apache.commons.logging.impl.Log4JLogger.warn(Log4JLogger.java:222)  
  17.     at com.opensymphony.xwork2.util.logging.commons.CommonsLogger.warn(CommonsLogger.java:56)  
  18.     at org.apache.struts2.components.ServletUrlRenderer.renderFormUrl(ServletUrlRenderer.java:186)  
  19.     at org.apache.struts2.components.Form.populateComponentHtmlId(Form.java:220)  
  20.     at org.apache.struts2.components.UIBean.evaluateParams(UIBean.java:784)  
  21.     at org.apache.struts2.components.ClosingUIBean.start(ClosingUIBean.java:57)  
  22.     at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:53)  
  23.     at org.apache.jsp.web.enterprise.add_jsp._jspx_meth_s_005fform_005f0(add_jsp.java:188)  
  24.     at org.apache.jsp.web.enterprise.add_jsp._jspx_meth_c_005fif_005f0(add_jsp.java:154)  
  25.     at org.apache.jsp.web.enterprise.add_jsp._jspService(add_jsp.java:115)  
  26.     at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)  
  27.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)  
  28.     at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)  
  29.     at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)  
  30.     at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)  
  31.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)  
  32.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)  
  33.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)  
  34.     at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:88)  
  35.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)  
  36.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)  
  37.     at com.yaxing.util.ResFilter.doFilter(ResFilter.java:63)  
  38.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)  
  39.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)  
  40.     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)  
  41.     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)  
  42.     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)  
  43.     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)  
  44.     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)  
  45.     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)  
  46.     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)  
  47.     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)  
  48.     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)  
  49.     at java.lang.Thread.run(Thread.java:619)  
  50.  
  51.  
  52.  

此错误表现为:执行查询语句没问题,但是执行插入的页面就都有问题,都报这错。很诡异的是,只打开这个页面就报错,而不管你执行了添加这个操作了没有,而且只报一次这个错,要想再见到这个错误,只有Redeploy了。。。。

虽然有这个错误,但是也不影响程序的执行。但是,咱是见不得项目中有些许的报错啊,心烦。

网上查了很多,

网上有人说是SQL语句的问题,一开始,也猜测是这种问题。但是检查了下SQL语句,发现并不是这个问题。

后来就怀疑是不是页面的问题,因为我打开这个添加的页面就报错,仔细一分析,排除了这种可能性!

再看看错误提示:log4j:ERROR Failed to excute sql

于是,八成是log4j的报错了。

log4j的配置文件如下:

 
  1. log4j.rootLogger=warn,db  
  2. log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender  
  3. log4j.appender.db.BufferSize=1 
  4. log4j.appender.db.URL=jdbc\:jtds\:sqlserver\://server\:1434/pcbsyn  
  5. log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver  
  6. log4j.appender.db.user=sa 
  7. log4j.appender.db.password=711 
  8. log4j.appender.db.sql=insert into logInfo(userId,userName,lclass,lmethod,lTime,llevel,message) values ('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH\:mm\:ss}','%p','%m')  
  9. log4j.appender.db.layout=org.apache.log4j.PatternLayout  
  10.  
  11.  
  12.  

于是,把log4j从项目中去掉!再发布运行,果然就没有报错了。

这配置文件中涉及到SQL语句的部分也只有第8行:

 

 
  1. log4j.appender.DATABASE.sql=insert into logInfo(userId,userName,lclass,lmethod,lTime,llevel,message)values('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%m') 

也只有这个里面出现了 单引号 " ' ".

 

 
  1. org.apache.log4j.jdbc.JDBCAppender 

从Apache网站上找到了下面的解释:

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/jdbc/JDBCAppender.html

The JDBCAppender provides for sending log events to a database.

WARNING: This version of JDBCAppender is very likely to be completely replaced in the future. Moreoever, it does not log exceptions.

Each append call adds to an ArrayList buffer. When the buffer is filled each log event is placed in a sql statement (configurable) and executed. BufferSizedb URLUser, & Password are configurable options in the standard log4j ways.

The setSql(String sql) sets the SQL statement to be used for logging -- this statement is sent to a PatternLayout (either created automaticly by the appender or added by the user). Therefore by default all the conversion patterns in PatternLayout can be used inside of the statement. (see the test cases for examples)

Overriding the getLogStatement(org.apache.log4j.spi.LoggingEvent) method allows more explicit control of the statement used for logging.

参见http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/jdbc/JDBCAppender.html

查看JDBCAppender.java的源代码如下:

 

 
  1. /**  
  2.    * loops through the buffer of LoggingEvents, gets a  
  3.    * sql string from getLogStatement() and sends it to execute().  
  4.    * Errors are sent to the errorHandler.  
  5.    *  
  6.    * If a statement fails the LoggingEvent stays in the buffer!  
  7.    */ 
  8.   public void flushBuffer() {  
  9.     //Do the actual logging  
  10.     removes.ensureCapacity(buffer.size());  
  11.     for (Iterator i = buffer.iterator(); i.hasNext();) {  
  12.       try {  
  13.         LoggingEvent logEvent = (LoggingEvent)i.next();  
  14.         String sql = getLogStatement(logEvent);  
  15.         execute(sql);  
  16.         removes.add(logEvent);  
  17.       }  
  18.       catch (SQLException e) {  
  19.         errorHandler.error("Failed to excute sql", e, //此处报错 
  20.                ErrorCode.FLUSH_FAILURE);  
  21.       }  
  22.     } 

由此找到了报错的来源:程序第19行报错!这个方法的介绍,可以查看上面的注释部分。

重写JDBCAppender:

MyJDBCAppender.java 继承

getLogStatement()这个方法即可!具体的可以查看 org.apache.log4j.jdbc.JDBCAppender.java这个类的源代码!

 
  1. package com.yaxing.util;  
  2.  
  3. import org.apache.log4j.Category;  
  4. import org.apache.log4j.Logger;  
  5. import org.apache.log4j.Priority;  
  6. import org.apache.log4j.jdbc.JDBCAppender;  
  7. import org.apache.log4j.spi.LoggingEvent;  
  8.  
  9. public class MyJDBCAppender extends JDBCAppender {  
  10.     @Override 
  11.     protected String getLogStatement(LoggingEvent event) {  
  12.         String fqnOfCategoryClass = event.fqnOfCategoryClass;  
  13.         Category logger = Logger.getRootLogger();  
  14.         Priority level = event.getLevel();  
  15.         Object message = event.getMessage();  
  16.         Throwable throwable = null;  
  17.         LoggingEventUtil bEvent = new LoggingEventUtil(fqnOfCategoryClass, logger,  
  18.                 level, message, throwable);  
  19.         return super.getLogStatement(bEvent);  
  20.     }  


LoggingEventUtil.java继承 LoggingEvent :
 

覆盖里面的

 

 

 
  1. @Override 
  2. public String getThreadName() {  
  3.     String thrdName = super.getThreadName();  
  4.     if (thrdName.indexOf("'") != -1) {  
  5.         thrdName = thrdName.replaceAll("'""''");  
  6.     }  
  7.     return thrdName;  

即可!
 

 
  1. package com.yaxing.util;  
  2.  
  3. import org.apache.log4j.Category;  
  4. import org.apache.log4j.Priority;  
  5. import org.apache.log4j.spi.LoggingEvent;  
  6.  
  7. public class LoggingEventUtil extends LoggingEvent {  
  8.     private static final long serialVersionUID = 3359112146209080210L;  
  9.  
  10.     public LoggingEventUtil(String fqnOfCategoryClass, Category logger,  
  11.             Priority level, Object message, Throwable throwable) {  
  12.         super(fqnOfCategoryClass, logger, level, message, throwable);  
  13.     }  
  14.  
  15.     @Override 
  16.     public String getThreadName() {  
  17.         String thrdName = super.getThreadName();  
  18.         if (thrdName.indexOf("'") != -1) {  
  19.             thrdName = thrdName.replaceAll("'""''");  
  20.         }  
  21.         return thrdName;  
  22.     }  
  23.  
  24.     /**  
  25.      *   
  26.      *   
  27.      * @see org.apache.log4j.spi.LoggingEvent#getRenderedMessage()  
  28.      */ 
  29.     @Override 
  30.     public String getRenderedMessage() {  
  31.         String renderedMessage = super.getRenderedMessage();  
  32.  
  33.         if (renderedMessage != null && renderedMessage.indexOf("'") != -1)  
  34.             renderedMessage = renderedMessage.replaceAll("'""''");  
  35.         return renderedMessage;  
  36.     }  

最后在log4j.properties里面使用我们自定义的JDBCAppender-->MyJDBCAppender

到此,大功告成!

 


 本文转自 w156445045 51CTO博客,原文链接:http://blog.51cto.com/enetq/764054,如需转载请自行联系原作者


相关文章
|
3月前
|
SQL 数据库 数据安全/隐私保护
SQL Server数据库Owner导致事务复制log reader job无法启动的解决办法
【8月更文挑战第14天】解决SQL Server事务复制Log Reader作业因数据库所有者问题无法启动的方法:首先验证数据库所有者是否有效并具足够权限;若非,使用`ALTER AUTHORIZATION`更改为有效登录名。其次,确认Log Reader使用的登录名拥有读取事务日志所需的角色权限。还需检查复制配置是否准确无误,并验证Log Reader代理的连接信息及参数。重启SQL Server Agent服务或手动启动Log Reader作业亦可能解决问题。最后,审查SQL Server错误日志及Windows事件查看器以获取更多线索。
|
6天前
|
SQL Java 数据库连接
[SQL]SQL注入与SQL执行过程(基于JDBC)
本文介绍了SQL注入的概念及其危害,通过示例说明了恶意输入如何导致SQL语句异常执行。同时,详细解释了SQL语句的执行过程,并提出了使用PreparedStatement来防止SQL注入的方法。
26 1
|
6月前
|
SQL Java 关系型数据库
实时计算 Flink版操作报错之如何处理从源表插入数据到结果表报错误:[ERROR] Could not execute SQL statement.
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
6月前
|
SQL Java 数据库连接
JDBC的连接参数的设置导致rowid自动添加到sql
JDBC的连接参数的设置导致rowid自动添加到sql
50 1
|
1月前
|
SQL 分布式计算 Java
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
33 0
|
1月前
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
79 0
|
1月前
|
SQL 分布式计算 关系型数据库
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
35 0
|
1月前
|
SQL 分布式计算 关系型数据库
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
44 0
|
3月前
|
SQL Java 数据库连接
JDBC连接SQL Server2008 完成增加、删除、查询、修改等基本信息基本格式及示例代码
这篇文章提供了使用JDBC连接SQL Server 2008数据库进行增加、删除、查询和修改操作的基本步骤和示例代码。
|
4月前
|
SQL Cloud Native 关系型数据库
云原生数据仓库使用问题之控制JDBC方式请求的SQL大小限制的参数是什么
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。