Search code examples
javamysqlcase-sensitivedbunit

DbUnit: NoSuchColumnException and case sensitivity


Before posting this I googled a bit, I looked for in dbunit-user archives and a bit also in DbUnit bug list, but I'm not found what looking for. Unfortunately, answers here did not help me either.

I'm using DbUnit 2.4.8 with MySQL 5.1.x to populate in setUp some JForum tables. The issue is first appearing on jforum_users table created by this 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 '',
       `user_password` VARCHAR(32) NOT NULL DEFAULT '',
       [...]
       PRIMARY KEY (`user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=14

Executing REFRESH as database setup operation the following exception is raised.

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)

I looked in AbstractTableMetaData.java sources and nothing seems -statically- wrong. The method

private Map createColumnIndexesMap(Column[] columns)

uses

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

in writing map keys. And then the method

public int getColumnIndex(String columnName)

uses

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

to read object from the map.

I really can't undestand what's going on... Anybody can help me please?

Edit after last @limc answer

I'm using a PropertiesBasedJdbcDatabaseTester to configure my DbUnit env, as follow:

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

Solution

  • I have reason to believe the problem stemmed from user_id column as the record ID. I have similar problem in the past where the row ID is generated natively by SQL Server. I'm not at my work desk now, but try this solution to see if it helps: http://old.nabble.com/case-sensitivity-on-tearDown--td22964025.html

    UPDATE - 02-03-11

    I have a working solution here. Here's my test code:-

    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 Test File

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

    I didn't get any errors, and the row was added into the database.

    Just FYI, I did try a REFRESH and that works fine without errors too:-

    DatabaseOperation.REFRESH.execute(con, dataSet);
    

    I'm using DBUnit 2.4.8 and MySQL 5.1.44.

    Hope this helps.