org.dbunit.dataset.NoSuchColumnException

Я получаю следующую ошибку при запуске моих тестов:

org.dbunit.dataset.NoSuchColumnException: myTable.MYFIELD -  (Non-uppercase input column: myfield) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.
    at org.dbunit.dataset.AbstractTableMetaData.getColumnIndex(AbstractTableMetaData.java:117)

Я установил точку останова в org.dbunit.dataset.AbstractTableMetaData#getColumnIndex и обнаружил следующее. В IntelliJ Idea метод выглядит так:

public int getColumnIndex(String columnName) throws DataSetException 
{
    logger.debug("getColumnIndex(columnName={}) - start", columnName);

    if(this._columnsToIndexes == null) 
    {
        // lazily create the map
        this._columnsToIndexes = createColumnIndexesMap(this.getColumns());
    }

    String columnNameUpperCase = columnName.toUpperCase();
    Integer colIndex = (Integer) this._columnsToIndexes.get(columnNameUpperCase);
    if(colIndex != null) 
    {
        return colIndex.intValue();
    }
    else 
    {
        throw new NoSuchColumnException(this.getTableName(), columnNameUpperCase,
                " (Non-uppercase input column: "+columnName+") in ColumnNameToIndexes cache map. " +
                "Note that the map's column names are NOT case sensitive.");
    }
}

Значение this.getColumns() не содержит никаких Column с Column.columnName соответствие параметра columnName, Следовательно colIndex становится null и исключение брошено.

Похоже, DBUnit ищет индекс столбца в неверных метаданных таблицы.

Как я могу это исправить?

Примечание: я унаследовал этот код от кого-то другого (не писал его).

2 ответа

Решение

Я чувствую тот факт, что вы не можете поделиться кодом. Это делает вещи немного сложными, но вот ответ, который я считаю разумным, учитывая ограничения:

Я смог легко воспроизвести это исключение, используя минимальный проект Spring Boot/DbUnit, клонированный из GitHub. Возможно, мои наблюдения составят подсказку, которую вы ищете, или, по крайней мере, вдохновят на лучший ответ.

меры

  • Клонировать проект и установить зависимости.
  • Запустить HsqldbexampleApplicationTests.contextLoads() тестовое задание. Это проходит.
  • Попасть в StaticResource.javaи изменить один из @Column аннотаций.

Например, я изменил:

@Column(name = "CONTENT")
private String content;

чтобы:

@Column(name = "CONTENTZ")
private String content;
  • Запустите тест снова и соблюдайте исключение
  • Кроме того, вы можете попасть в sampleData.xml и изменить CONTENT Атрибуты там (имя атрибута), чтобы произвести то же исключение.

наблюдения

  • Тест получает данные от /META-INF/dbtest/sampleData.xml, Обратите внимание CONTENT приписывать.
  • Ресурс имеет @Column аннотация которого name должен соответствовать атрибуту, найденному в sampleData.xml элементы.
  • Поскольку ваша проблема также связана с запуском тестов, возможно, ваш код и .xml(?), который увлажняет ваше тестовое хранилище данных, просто не синхронизировано по отношению к имени столбца.

Дальнейшее значение файла XML?

Мои попытки спровоцировать это исключение путем изменения запросов и имен переменных экземпляра не увенчались успехом. Все, что я пробовал, заставляло компилятор жаловаться, поэтому я исключил это.

Например, я также проверил этот репозиторий и попытался изменить запрос и переменную экземпляра, но компилятор мешал на каждом этапе. Изменение запроса:

Изменение ошибки запроса

Изменение имени переменной экземпляра:

Ошибка изменения имени переменной

Где искать

  • В любом месте в любом коде Java, где у вас есть @Column с MYFIELD внутри него. Помните, аннотации могут занимать несколько строк в файле.
  • Любые XML-файлы, содержащие MYFIELD,
  • Предполагая, что тестируемый код работает нормально, а ваши проблемы ограничиваются запуском тестов, механизм, который вводит данные в ваш тест, является основным подозреваемым. Если это не XML-файл, что это?

Не понятно из вашего поста, как вы получаете _columnsToIndexes Это похоже на часть кода отражения, который зависит от вашего POJO. В этом случае проблема может быть в Lazy инициализация объекта. Ленивые инициализированные объекты - это не просто объект-сущность, а своего рода прокси-сервер, и попытка получить его свойства через отражение может вызвать эту проблему. Вероятно, вы должны попытаться добавить какой-то метод прокси в вас createColumnIndexesMap, Вот пример:

public static <T> T initializeAndUnproxy(T entity) {
    if (entity == null) {
      throw new InternalServerException("Entity passed for initialization is null");
    }

    T unproxy = entity;
    Hibernate.initialize(entity);
    if (isProxy(entity)) {
      unproxy = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
    }
    return unproxy;
  }
  public static <T> boolean isProxy(T entity) {
    return entity instanceof HibernateProxy;
  }

конечно это зависит от вашего ORM, вот пример для Hibernate

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