Log4J2 JdbcAppender не составляет правильную инструкцию INSERT

Я пытаюсь войти в базу данных PostgreSQL с помощью этого объединенного регистратора JDBC в моем приложении Spring.

Основная идея исходит отсюда: Как инициализировать log4j с помощью приложения Spring Boot?

@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 ERROR Невозможно записать в база данных [JdbcManager {имя = databaseAppender, bufferSize = 0, tableName=logs2, columnConfigs=[{ name=level, layout=%level, literal=null, timestamp=false }], columnMappings=null}] для добавления [приложение базы данных]. org.apache.logging.log4j.core.appender.db.DbAppenderLoggingException: Не удалось вставить запись для события журнала в диспетчере JDBC: org.postgresql.util.PSQLException: ОШИБКА: синтаксическая ошибка в или около ")" Позиция: 20 [columnConfigs=[{ name=level, layout=%level, literal=null, timestamp=false }], sqlStatement=вставить в logs2 () значения (?), factoryData = Заводские данные [connectionSource=ConnectionFactory@ca2c455, tableName=logs2, columnConfigs=[{ name=level, layout=%level, литерал = ноль, временная метка = ложь}], столбецMappings = ноль, непосредственныйFail=false, повтор=true, reconnectIntervalMillis=5000, truncateStrings=true], соединение=HikariProxyConnection@1535828764 упаковка org.postgresql.jdbc.PgConnection@603942ae, заявление = HikariProxyPreparedStatement@1512335087 оберточная вставка в значения logs2 () («INFO»), reconnector=null, isBatchSupported=true, столбецMetaData = {}]

есть проблема с недействительным оператором SQL INSERT:

sqlStatement=вставить в logs2() значения (?),

Вопрос: У вас есть идея, почему log4J не правильно/полностью составляет команду? Что не так с моим кодом?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
787
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это ошибка в Log4j2.

Я настроил быстрый проект в IntelliJ, добавил log4j2 2.14 API и основные JAR-файлы, а также JAR-файл драйвера базы данных и запустил ваш код, и мне удалось воспроизвести неправильно отформатированный оператор INSERT в вашем сообщении об ошибке.

Я использовал IntelliJ, чтобы загрузить исходный JAR-файл log4j2 и прикрепить его, а также прошел код, который собрал оператор 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
                }
            }
        }

В этом случае мы видим, что имена столбцов из ColumnConfigs не используются, если ColumnMappings являются null. Такое поведение неверно: вы должны указать только ColumnConfigs. Второй if не должен быть вложен в первый.

Log4j2 поддерживает использование ColumnMappings, а также ColumnConfigs для указания столбцов для записи в вашей таблице журналов, поэтому одним из обходных путей является использование их вместо этого. Альтернативный обходной путь — добавить строку

        .setColumnMappings(new ColumnMapping[0])

на строительство вашего JdbcAppender. Я внес это изменение в ваш код, и Log4j2 сгенерировал правильную строку SQL.

Да, тем временем я тоже это понял - мне нужно назначить пустой ColumnMapping final ColumnMapping[] columnMappings = new ColumnMapping[0];

Artegon 12.12.2020 12:21

Другие вопросы по теме