解决方案 »

  1.   

    Log4J 的 JDBCAppender 是明显有 bug 的,它原来的那个是用大致用这个办法:javax.sql.Connection.createStatement().executeUpdate(PatternLayout.format(yourMessage)); ,很明显你看出来了,字符串拼接又不做转义字符替换,只要字符串中包括了单引号时它就出现  SQL 语法错误。
    ,所以我们不要用它那个,自己写一个 JDBC Appender 来用 PreparedStatement 改造吧,从 logging.apache.org 上去下载它的源码来继承它改写一个自己的版本的 MyJDBCAppender 类来用。
      

  2.   

    https://svn.apache.org/repos/asf/logging/log4j/trunk/src/main/java/org/apache/log4j/PatternLayout.java从这个 PatternLayout 的:public String format(LoggingEvent event);方法来看,它没考虑到字符串中本身有单引号的问题。
    因此我们写一个类继承它覆盖这个方法,并把它的返回值中的单引号转换替换一次(把一个单引号替换成两个连续的单引号 )。
    这是最简单的修正方法了,不过最好的办法还是写自己的 appender 用 PreparedStatement 来做。
      

  3.   

    https://svn.apache.org/repos/asf/logging/log4j/trunk/src/main/java/org/apache/log4j/jdbc/JDBCAppender.java当然,最好的办法就是继承这个类把它的 flushBuffer() 方法中那个操作数据库的地方: String sql = getLogStatement(logEvent);
    execute(sql);
    改成: PreparedStatement stmt = conn.prepareStatement(getSql());
    stmt.setString(1, getLayout().format(loggingEvent);
    stmt.executeUpdate();注意这是假设我们的 SQL 语句将会是,类似下面这样,留下一个参数位给 msg 本身:
     
    insert into tableName(..., ?)