log4j2 jdbcapender无法编写正确的insert语句

vlf7wbxs  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(251)

我正试图在我的spring应用程序中使用这个池jdbc记录器登录postgresql数据库。
主要思想来自这里:如何用spring引导应用程序初始化log4j?

@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:05860重新启动主错误无法写入appender[databaseappender]的数据库[jdbcmanager{name=databaseappender,buffersize=0,tablename=logs2,columnconfigs=[{name=level,layout=%level,literal=null,timestamp=false}],columnmappings=null}]。org.apache.logging.log4j.core.appender.db.dbappenderlogingexception:未能在jdbc管理器中插入日志事件的记录:org.postgresql.util.psqleexception:错误:语法错误位于或接近“)”pozice:20[columnconfigs=[{name=level,layout=%level,literal=null,timestamp=false}],sqlstatement=insert into logs2()值(?),factorydata=工厂数据[connectionsource=connectionfactory@ca2c455,tablename=logs2,columnconfigs=[{name=level,layout=%level,literal=null,timestamp=false}],columnmappings=null,immediatefail=false,retry=true,reconnectintervalmillis=5000,truncatestrings=true], connection=hikariproxyconnection@1535828764 Package org.postgresql.jdbc。pgconnection@603942ae, statement=hikariproxypreparedstatement@1512335087 将insert Package 到logs2()值('info'),reconnector=null,isbatchsupported=true,columnmetadata={}]
无效的sql insert语句有问题:
sqlstatement=insert into logs2()值(?),
问:您知道为什么log4j不能正确/完整地编写命令吗?我的代码怎么了?

ibrsph3r

ibrsph3r1#

这是log4j2中的一个bug。
我在intellij中建立了一个quick项目,添加了log4j22.14api、核心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
                }
            }
        }

在本例中,我们可以看到 ColumnConfig 如果 ColumnMapping s是 null . 这种行为是不正确的:您应该能够指定 ColumnConfig 只有她。第二个 if 不应嵌套在第一个。
log4j2支持 ColumnMapping 以及 ColumnConfig 用于在日志表中指定要写入的列,因此一种解决方法是使用这些列。另一种解决方法是添加行

.setColumnMappings(new ColumnMapping[0])

你的建筑 JdbcAppender . 我对您的代码进行了更改,log4j2生成了正确的sql字符串。

相关问题