DbUnit: NoSuchColumnException и чувствительность к регистру - PullRequest
15 голосов
/ 02 февраля 2011

Перед публикацией я немного погуглил, искал в dbunit-user архивы и немного также в списке ошибок DbUnit, но я не нашел, что находясь в поиске. К сожалению, ответы здесь мне тоже не помогли.

Я использую DbUnit 2.4.8 с MySQL 5.1.x для заполнения в setUp некоторых таблиц JForum. Проблема впервые появляется в таблице jforum_users, созданной этим сценарием

CREATE TABLE `jforum_users` (
       `user_id` INT(11) NOT NULL AUTO_INCREMENT,
       `user_active` TINYINT(1) NULL DEFAULT NULL,
       `username` VARCHAR(50) NOT NULL DEFAULT '',
       `user_password` VARCHAR(32) NOT NULL DEFAULT '',
       [...]
       PRIMARY KEY (`user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=14

При выполнении REFRESH в качестве операции настройки базы данных возникает следующее исключение.

org.dbunit.dataset.NoSuchColumnException: jforum_users.USER_ID -
(Non-uppercase input column: USER_ID) in ColumnNameToIndexes cache
map. Note that the map's column names are NOT case sensitive.
       at org.dbunit.dataset.AbstractTableMetaData.getColumnIndex(AbstractTableMetaData.java:117)
       at org.dbunit.operation.AbstractOperation.getOperationMetaData(AbstractOperation.java:89)
       at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:98)
       at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
       at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
       at net.jforum.dao.generic.AbstractDaoTest.setUpDatabase(AbstractDaoTest.java:43)

Я посмотрел в AbstractTableMetaData.java источниках, и ничто не кажется - статически - неправильным. Метод

private Map createColumnIndexesMap(Column[] columns)

использует

columns[i].getColumnName().toUpperCase()

при написании ключей карты. И тогда метод

public int getColumnIndex(String columnName)

использует

String columnNameUpperCase = columnName.toUpperCase();
Integer colIndex = (Integer) this._columnsToIndexes.get(columnNameUpperCase);

для чтения объекта с карты.

Я действительно не могу понять, что происходит ... Кто-нибудь может мне помочь, пожалуйста?

Редактировать после последнего @limc ответа

Я использую PropertiesBasedJdbcDatabaseTester для настройки моего окружения DbUnit следующим образом:

Properties dbProperties = new Properties();
dbProperties.load(new FileInputStream(testConfDir+"/db.properties"));
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, 
    dbProperties.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS));
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, 
    dbProperties.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL));
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, 
    dbProperties.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME));
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, 
    dbProperties.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD));
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_SCHEMA, 
    dbProperties.getProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_SCHEMA));

databaseTester = new PropertiesBasedJdbcDatabaseTester();
databaseTester.setSetUpOperation(getSetUpOperation());
databaseTester.setTearDownOperation(getTearDownOperation());

IDataSet dataSet = getDataSet();
databaseTester.setDataSet(dataSet);

databaseTester.onSetup();

Ответы [ 9 ]

6 голосов
/ 06 января 2014

У меня была похожая проблема с этим сегодня (с использованием интерфейса IDatabaseTester, добавленного в v2.2 против MySQL), и я потратил несколько часов на то, чтобы вычесать мне волосы.OP использует PropertiesBasedJdbcDatabaseTester, в то время как я использовал его «родительский» JdbcDatabaseTester.

DBUnit имеет ответ на часто задаваемые вопросы, связанный с этим NoSuchColumnException (специфично для MySQL), но выглядит как недосмотрМне не следует упоминать, что каждое соединение, полученное из метода getConnection () интерфейса , будет иметь отдельную конфигурацию.На самом деле, я бы назвал это ошибкой, учитывая формулировку различных битов документа, которые я просматривал сегодня, и названия участвующих классов (например, DatabaseConfig, но для каждого соединения?).

В любом случае, в таких разделах кода, как setup / teardown (пример ниже), вы даже не предоставляете объект Connection, поэтому я не вижу способа установить там конфигурацию.

dbTester.setDataSet(beforeData);
dbTester.onSetup();

В конце япросто расширили JdbcDatabaseTester для @Override метода getConnection () и каждый раз вводите конфигурацию, специфичную для MySQL:

class MySQLJdbcDatabaseTester extends org.dbunit.JdbcDatabaseTester {
  public MySQLJdbcDatabaseTester(String driverClass, String connectionUrl, String username, String password,
                                 String schema) throws ClassNotFoundException {
    super(driverClass, connectionUrl, username, password, schema);
  }

  @Override
  public IDatabaseConnection getConnection() throws Exception {
    IDatabaseConnection connection = super.getConnection();
    DatabaseConfig dbConfig = connection.getConfig();
    dbConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory());
    dbConfig.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler());
    return connection;
  }
}

И, наконец, все ошибки исчезли.

3 голосов
/ 03 февраля 2011

У меня есть основания полагать, что проблема возникла из столбца user_id в качестве идентификатора записи.У меня была похожая проблема в прошлом, когда идентификатор строки генерируется SQL Server.Сейчас я не за рабочим столом, но попробуйте это решение, чтобы увидеть, поможет ли оно: http://old.nabble.com/case-sensitivity-on-tearDown--td22964025.html

ОБНОВЛЕНИЕ - 02-03-11

У меня естьрабочее решение здесь.Вот мой тестовый код: -

MySQL Script

CREATE TABLE `jforum_users` (
       `user_id` INT(11) NOT NULL AUTO_INCREMENT,
       `user_active` TINYINT(1) NULL DEFAULT NULL,
       `username` VARCHAR(50) NOT NULL DEFAULT '',
       PRIMARY KEY (`user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=14

dbunit-test.xml Тестовый файл

<?xml version='1.0' encoding='UTF-8'?>

<dataset>
    <jforum_users user_id="100" username="First User" />
</dataset>

Java Code

Class.forName("com.mysql.jdbc.Driver");
Connection jdbcConnection = DriverManager.getConnection("jdbc:mysql://localhost:8889/test", "", "");
IDatabaseConnection con = new DatabaseConnection(jdbcConnection);

InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit-test.xml");
IDataSet dataSet = new FlatXmlDataSetBuilder().build(is);
DatabaseOperation.CLEAN_INSERT.execute(con, dataSet);

con.close();

Я не получил никаких ошибок, и строка была добавлена ​​в базу данных.

Просто к вашему сведению, я попробовал REFRESH и это прекрасно работает без ошибок: -

DatabaseOperation.REFRESH.execute(con, dataSet);

Я использую DBUnit 2.4.8 и MySQL 5.1.44.

Надеюсь, это поможет.

2 голосов
/ 20 марта 2017

Когда я получил эту ошибку, это произошло из-за того, что моя схема имела ненулевое ограничение для столбца, но этот столбец отсутствовал в моем файле данных.

Например, в моей таблице было

<table name="mytable">
    <column>id</column>
    <column>entity_type</column>
    <column>deleted</column>
</table>

<dataset>
    <mytable id="100" entity_type"2"/>
</dataset>

У меня есть ненулевое ограничение на удаленный столбец, и когда я запускаю тест, я получаю исключение NoSuchColumnException.

Когда я изменяю набор данных на

<mytable id="100" entity_type"2" deleted="0"/>

, я получаю послеИсключение.

2 голосов
/ 01 апреля 2015

Я пришел сюда в поисках ответа на эту проблему. Для меня проблема была в Hibernate Naming Strategy. Я понял, что это проблема, так как show_sql был верным в приложении Spring.properties:

spring.jpa.show-sql=true

Я мог видеть сгенерированную таблицу SQL и имя поля было «FACT_NUMBER» вместо «factNumber», которое я имел в xml моего dbunit.

Эта проблема была решена путем применения стратегии именования по умолчанию (по иронии судьбы, по умолчанию, похоже, org.hibernate.cfg.ImprovedNamingStrategy, которая добавляет '_'):

spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
0 голосов
/ 13 марта 2018

Я только что наткнулся на это сообщение об ошибке.

Мне пришлось расширить старый кусок кода - мне нужно было добавить новый столбец в несколько таблиц.В одной из моих сущностей я забыл создать setter для этого столбца.Таким образом, вы можете проверить свои сущности, если они «завершены».

Иногда это может быть так просто.

0 голосов
/ 10 мая 2017

У меня была та же проблема, но я решил, что в моей базе данных используется другое имя столбца, чем то, что есть в моем XML-файле.

Я уверен, что у вас есть проблема в идентификаторе пользователя и USER_ID.

0 голосов
/ 01 ноября 2016

Ну, в моем случае это был CSV-файл, закодированный в UTF-8 с символом BOM в начале.Я использовал блокнот для создания CSV-файлов.Используйте notepade ++, чтобы избежать сохранения символа спецификации.

0 голосов
/ 26 ноября 2015

Я столкнулся с этой проблемой, и причина была в том, что у dtd моего файла набора данных было описание, отличное от таблицы, в которую я хотел вставить данные.

Так что проверьте, что ваша таблица, куда вы хотите вставитьданные имеют те же столбцы, что и ваш файл dtd.

когда я удаляю в файле dtd столбец, которого не было в таблице, куда я вставил данные, проблема исчезла.

0 голосов
/ 21 ноября 2013

Хорошо. Я столкнулся с той же проблемой, и нашел решение: неправильный способ создания тестовых данных, для какого набора данных мы использовали Вы используете FlatXmlDataSet, тогда существует другой формат, подробности см. в ссылке, приведенной ниже. XML должен быть в следующем формате.

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <table>
        <column>id</column>
        <column>name</column>
        <column>department</column>
        <column>startDate</column>
        <column>endDate</column>
        <row>
            <value>999</value>
            <value>TEMP</value>
            <value>TEMP DEPT</value>
            <value>2113-10-13</value>
            <value>2123-10-13</value>
        </row>
    </table>
</dataset>

Если вы хотите узнать больше, перейдите по этой ссылке: http://dbunit.sourceforge.net/components.html

...