项目中一直报如下的错误:
项目架构如下:Struts2.2.3 +Hibernate3.3 +Spirng 3.0 +Log4J-1.2.16+jtds-1.2.5.
- log4j:ERROR Failed to excute sql
- java.sql.SQLException: Invalid SQL statement or JDBC escape, terminating ''' not found.
- at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:1155)
- at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:156)
- at net.sourceforge.jtds.jdbc.JtdsStatement.executeImpl(JtdsStatement.java:684)
- at net.sourceforge.jtds.jdbc.JtdsStatement.executeUpdate(JtdsStatement.java:1166)
- at net.sourceforge.jtds.jdbc.JtdsStatement.executeUpdate(JtdsStatement.java:1119)
- at org.apache.log4j.jdbc.JDBCAppender.execute(JDBCAppender.java:178)
- at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:250)
- at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:146)
- at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
- at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
- at org.apache.log4j.Category.callAppenders(Category.java:206)
- at org.apache.log4j.Category.forcedLog(Category.java:391)
- at org.apache.log4j.Category.log(Category.java:856)
- at org.apache.commons.logging.impl.Log4JLogger.warn(Log4JLogger.java:222)
- at com.opensymphony.xwork2.util.logging.commons.CommonsLogger.warn(CommonsLogger.java:56)
- at org.apache.struts2.components.ServletUrlRenderer.renderFormUrl(ServletUrlRenderer.java:186)
- at org.apache.struts2.components.Form.populateComponentHtmlId(Form.java:220)
- at org.apache.struts2.components.UIBean.evaluateParams(UIBean.java:784)
- at org.apache.struts2.components.ClosingUIBean.start(ClosingUIBean.java:57)
- at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:53)
- at org.apache.jsp.web.enterprise.add_jsp._jspx_meth_s_005fform_005f0(add_jsp.java:188)
- at org.apache.jsp.web.enterprise.add_jsp._jspx_meth_c_005fif_005f0(add_jsp.java:154)
- at org.apache.jsp.web.enterprise.add_jsp._jspService(add_jsp.java:115)
- at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
- at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
- at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
- at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
- at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
- at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
- at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:88)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
- at com.yaxing.util.ResFilter.doFilter(ResFilter.java:63)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
- at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
- at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
- at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
- at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
- at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
- at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
- at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
- at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
- at java.lang.Thread.run(Thread.java:619)
此错误表现为:执行查询语句没问题,但是执行插入的页面就都有问题,都报这错。很诡异的是,只打开这个页面就报错,而不管你执行了添加这个操作了没有,而且只报一次这个错,要想再见到这个错误,只有Redeploy了。。。。
虽然有这个错误,但是也不影响程序的执行。但是,咱是见不得项目中有些许的报错啊,心烦。
网上查了很多,
网上有人说是SQL语句的问题,一开始,也猜测是这种问题。但是检查了下SQL语句,发现并不是这个问题。
后来就怀疑是不是页面的问题,因为我打开这个添加的页面就报错,仔细一分析,排除了这种可能性!
再看看错误提示:log4j:ERROR Failed to excute sql
于是,八成是log4j的报错了。
log4j的配置文件如下:
- log4j.rootLogger=warn,db
- log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender
- log4j.appender.db.BufferSize=1
- log4j.appender.db.URL=jdbc\:jtds\:sqlserver\://server\:1434/pcbsyn
- log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver
- log4j.appender.db.user=sa
- log4j.appender.db.password=711
- 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')
- log4j.appender.db.layout=org.apache.log4j.PatternLayout
于是,把log4j从项目中去掉!再发布运行,果然就没有报错了。
这配置文件中涉及到SQL语句的部分也只有第8行:
- 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')
也只有这个里面出现了 单引号 " ' ".
- 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. BufferSize, db URL, User, & 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的源代码如下:
- /**
- * loops through the buffer of LoggingEvents, gets a
- * sql string from getLogStatement() and sends it to execute().
- * Errors are sent to the errorHandler.
- *
- * If a statement fails the LoggingEvent stays in the buffer!
- */
- public void flushBuffer() {
- //Do the actual logging
- removes.ensureCapacity(buffer.size());
- for (Iterator i = buffer.iterator(); i.hasNext();) {
- try {
- LoggingEvent logEvent = (LoggingEvent)i.next();
- String sql = getLogStatement(logEvent);
- execute(sql);
- removes.add(logEvent);
- }
- catch (SQLException e) {
- errorHandler.error("Failed to excute sql", e, //此处报错
- ErrorCode.FLUSH_FAILURE);
- }
- }
由此找到了报错的来源:程序第19行报错!这个方法的介绍,可以查看上面的注释部分。
重写JDBCAppender:
MyJDBCAppender.java 继承
getLogStatement()这个方法即可!具体的可以查看 org.apache.log4j.jdbc.JDBCAppender.java这个类的源代码!
- package com.yaxing.util;
- import org.apache.log4j.Category;
- import org.apache.log4j.Logger;
- import org.apache.log4j.Priority;
- import org.apache.log4j.jdbc.JDBCAppender;
- import org.apache.log4j.spi.LoggingEvent;
- public class MyJDBCAppender extends JDBCAppender {
- @Override
- protected String getLogStatement(LoggingEvent event) {
- String fqnOfCategoryClass = event.fqnOfCategoryClass;
- Category logger = Logger.getRootLogger();
- Priority level = event.getLevel();
- Object message = event.getMessage();
- Throwable throwable = null;
- LoggingEventUtil bEvent = new LoggingEventUtil(fqnOfCategoryClass, logger,
- level, message, throwable);
- return super.getLogStatement(bEvent);
- }
- }
LoggingEventUtil.java继承 LoggingEvent :
覆盖里面的
- @Override
- public String getThreadName() {
- String thrdName = super.getThreadName();
- if (thrdName.indexOf("'") != -1) {
- thrdName = thrdName.replaceAll("'", "''");
- }
- return thrdName;
- }
即可!
- package com.yaxing.util;
- import org.apache.log4j.Category;
- import org.apache.log4j.Priority;
- import org.apache.log4j.spi.LoggingEvent;
- public class LoggingEventUtil extends LoggingEvent {
- private static final long serialVersionUID = 3359112146209080210L;
- public LoggingEventUtil(String fqnOfCategoryClass, Category logger,
- Priority level, Object message, Throwable throwable) {
- super(fqnOfCategoryClass, logger, level, message, throwable);
- }
- @Override
- public String getThreadName() {
- String thrdName = super.getThreadName();
- if (thrdName.indexOf("'") != -1) {
- thrdName = thrdName.replaceAll("'", "''");
- }
- return thrdName;
- }
- /**
- *
- *
- * @see org.apache.log4j.spi.LoggingEvent#getRenderedMessage()
- */
- @Override
- public String getRenderedMessage() {
- String renderedMessage = super.getRenderedMessage();
- if (renderedMessage != null && renderedMessage.indexOf("'") != -1)
- renderedMessage = renderedMessage.replaceAll("'", "''");
- return renderedMessage;
- }
- }
最后在log4j.properties里面使用我们自定义的JDBCAppender-->MyJDBCAppender
到此,大功告成!
本文转自 w156445045 51CTO博客,原文链接:http://blog.51cto.com/enetq/764054,如需转载请自行联系原作者