web-dev-qa-db-ja.com

DbUnit:NoSuchColumnExceptionと大文字と小文字の区別

これを投稿する前に、私は少しグーグルで検索し、dbunit-userアーカイブとDbUnitバグリストでも少し探しましたが、探しているものが見つかりません。残念ながら、答え ここ も私を助けませんでした。

MySQL5.1.xでDbUnit2.4.8を使用して、いくつかのJForumテーブルをsetUpに入力しています。この問題は、このスクリプトによって作成された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();
15

この問題は、レコードIDとしてのuser_id列に起因すると考える理由があります。行IDがSQLServerによってネイティブに生成されるという、過去にも同様の問題があります。私は現在ワークデスクにいませんが、このソリューションを試して、役立つかどうかを確認してください: http://old.nabble.com/case-sensitivevity-on-tearDown--td22964025.html

UPDATE-02-03-11

私はここに実用的な解決策を持っています。これが私のテストコードです:-

MySQLスクリプト

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コード

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);

DBUnit2.4.8とMySQL5.1.44を使用しています。

お役に立てれば。

3
limc

私は今日これと同様の問題を抱えており(MySQLに対してv2.2で追加されたIDatabaseTesterインターフェースを使用)、数時間かけて髪の毛を引き裂きました。 OPはPropertiesBasedJdbcDatabaseTesterを使用していますが、私はその「親」JdbcDatabaseTesterを使用していました。

DBUnitには a FAQこのNoSuchColumnExceptionに関連する回答 (MySQLに固有)がありますが、-から引き出された各接続について言及することを怠っているのは私には見落としのようです。 インターフェースのgetConnection()メソッド は個別の構成になります。実際、今日見たドコのさまざまなビットの表現と関連するクラスの名前を考えると、バグと呼ぶところまで行きます(例:DatabaseConfig、まだ接続ごと?)。

とにかく、セットアップ/ティアダウン(以下の例)のようなコードのセクションでは、Connectionオブジェクトさえ提供しないので、そこに構成を設定する方法がありません。

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

最後に、JdbcDatabaseTesterを拡張してgetConnection()メソッドを@Overrideし、毎回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;
  }
}

そしてついにすべてのエラーがなくなりました。

6
Greg Pendlebury

このエラーが発生したのは、スキーマの列にnull以外の制約があったためですが、この列がデータファイルにありませんでした。

たとえば、私のテーブルには

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

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

削除された列にnull以外の制約があり、テストを実行すると、NoSuchColumnExceptionが発生します。

データセットをに変更すると

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

私は例外を乗り越えます。

2
keith

私はこの問題の答えを探してここに来ました。私にとって問題は、Hibernateの命名戦略でした。 Springのapplication.propertiesでshow_sqlがtrueであったため、これが問題であることに気付きました。

spring.jpa.show-sql=true

生成されたテーブルSQLを確認でき、フィールド名は、dbunitのxmlにある「factNumber」ではなく「FACT_NUMBER」でした。

これは、デフォルトの命名戦略を強制することで解決されました(皮肉なことに、デフォルトはorg.hibernate.cfg.ImprovedNamingStrategyのようで、「_」を挿入します)。

spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
2
HankCa

私の場合は、最初にBOM文字を使用してUTF-8でエンコードされたcsvファイルでした。メモ帳を使用してcsvファイルを作成していました。 notepade ++を使用して、BOM文字の保存を回避します。

0
K. Apostolou

このエラーメッセージに出くわしました。

古いコードを拡張する必要がありました。いくつかのテーブルに新しい列を追加する必要がありました。私のエンティティの1つで、この列のセッターを作成するのを忘れました。したがって、エンティティが「完全」であるかどうかを確認できます。

時にはそれはそれと同じくらい簡単かもしれません。

0
morecore

同じ問題が発生した後、DBでXMLファイル内の列名とは異なる列名を使用していることがわかりました。

User_idとUSER_IDで問題が発生したと思います。

0
Fahad Mutair

私はこの問題に直面しました。その理由は、データセットファイルのdtdに、データを挿入したいテーブルとは異なる記述が含まれていたためです。

したがって、データを挿入するテーブルの列がdtdファイルと同じであることを確認してください。

dtdファイルでデータを挿入したテーブルになかった列を削除すると、問題は解消されました。

0
user5608583