【问题标题】:Log4J2 JdbcAppender doesn't compose correct INSERT statementLog4J2 JdbcAppender 没有组成正确的 INSERT 语句
【发布时间】:2021-03-23 12:36:14
【问题描述】:

我正在尝试在我的 Spring 应用程序中使用这个池化 JDBC 记录器登录 PostgreSQL 数据库。

主要思想来自这里:How to initialize log4j with Spring Boot application?

@Component
public class JdbcAppenderConfiguration implements 
                     ApplicationListener<ContextRefreshedEvent> {

  private static Logger LOGGER = 
      LogManager.getLogger(JdbcAppenderConfiguration.class);

  private final DataSource dataSource;

  public JdbcAppenderConfiguration(DataSource dataSource) {
      this.dataSource = dataSource;
  }

  @Override
  public void onApplicationEvent(ContextRefreshedEvent event) {

    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final ColumnConfig[] cc = {
        ColumnConfig.newBuilder()
            .setConfiguration(ctx.getConfiguration())
            .setName("level")
            .setPattern("%level")
            .setUnicode(false)
            .build()
    };

    final Appender appender = JdbcAppender
        .newBuilder()
        .setName("databaseAppender")
        .setIgnoreExceptions(false)
        .setConnectionSource(new ConnectionFactory(dataSource))
        .setTableName("logs2")
        .setColumnConfigs(cc)
        .build();

    appender.start();

    ctx.getConfiguration().addAppender(appender);

    final LoggerConfig loggerConfig =
        ctx.getConfiguration()
           .getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
    loggerConfig.addAppender(appender, null, null);

    ctx.updateLoggers();

  }

}

和连接工厂:

public class ConnectionFactory extends AbstractConnectionSource {

  private final DataSource dataSource;

  public ConnectionFactory(DataSource dataSource) {
    AssertUtils.notNull(dataSource, "dataSource");
    this.dataSource = dataSource;
  }

  @Override
  public Connection getConnection() throws SQLException {
    return dataSource.getConnection();
  }

}

但是在登录时我得到了这个错误:

2020-12-12 08:03:05,860 restartedMain 错误无法写入 数据库 [JdbcManager{name=databaseAppender, bufferSize=0, tableName=logs2, columnConfigs=[{ name=level, layout=%level, 文字=null,时间戳=false }],columnMappings=null}] 用于追加器 [数据库应用程序]。 org.apache.logging.log4j.core.appender.db.DbAppenderLoggingException: 在 JDBC 管理器中插入日志事件记录失败: org.postgresql.util.PSQLException:错误:“)”处或附近的语法错误 Pozice: 20 [columnConfigs=[{ name=level, layout=%level, literal=null, timestamp=false }], sqlStatement=insert into logs2 () values (?), 工厂数据=工厂数据 [connectionSource=ConnectionFactory@ca2c455, tableName=logs2, columnConfigs=[{ name=level, layout=%level, 文字=null,时间戳=false }],columnMappings=null, immediateFail=false,重试=true,reconnectIntervalMillis=5000, truncateStrings=true],连接=HikariProxyConnection@1535828764 包装 org.postgresql.jdbc.PgConnection@603942ae, statement=HikariProxyPreparedStatement@1512335087 包装插入到 logs2 () 值 ('INFO'), reconnector=null, isBatchSupported=true, columnMetaData={}]

无效的 SQL INSERT 语句存在问题:

sqlStatement=insert into logs2() values (?),

问题:你知道为什么 log4J 不能正确/完整地编写命令吗?我的代码有什么问题?

【问题讨论】:

    标签: java spring-boot log4j2


    【解决方案1】:

    这是 Log4j2 中的一个错误。

    我在 IntelliJ 中建立了一个快速项目,添加了 log4j2 2.14 api 和核心 JAR 以及数据库驱动程序 JAR 并运行了您的代码,我能够在您的错误消息中重现格式不正确的 INSERT 语句。

    我使用 IntelliJ 下载了 log4j2 源 JAR 并将其附加,并逐步完成了将 INSERT 语句放在一起的代码。将列名添加到 SQL 字符串的方法称为 appendColumnNames,位于类 JdbcDatabaseManager 中。 它包含以下代码,为了清楚起见,我对其进行了缩写:

            if (data.columnMappings != null) {
                for (final ColumnMapping colMapping : data.columnMappings) {
                    // append column from colMapping
                }
                if (data.columnConfigs != null) {
                    for (final ColumnConfig colConfig : data.columnConfigs) {
                        // append column from colConfig
                    }
                }
            }
    

    在这种情况下,如果ColumnMappings 是null,我们可以看到来自ColumnConfigs 的列名没有被使用。这种行为是不正确的:您应该只能指定ColumnConfigs。第二个if 不应嵌套在第一个内部。

    Log4j2 支持使用 ColumnMappings 和 ColumnConfigs 来指定要写入日志记录表中的列,因此一种解决方法是改用它们。另一种解决方法是添加该行

            .setColumnMappings(new ColumnMapping[0])
    

    来建设你的JdbcAppender。我对您的代码进行了此更改,Log4j2 生成了正确的 SQL 字符串。

    【讨论】:

    • 是的,同时我也意识到了——我必须分配一个空的 ColumnMapping final ColumnMapping[] columnMappings = new ColumnMapping[0];
    猜你喜欢
    • 2017-05-26
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 2011-05-12
    • 2018-08-03
    • 2015-01-10
    相关资源
    最近更新 更多