DbUnit:NoSuchColumnException 和区分大小写

2022-09-03 07:25:24

在发布此内容之前,我用谷歌搜索了一下,我在dbunit用户存档中查找了一下,并且在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

将刷新作为数据库设置操作执行时,将引发以下异常。

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答案之后编辑

我正在使用 a 来配置我的 DbUnit env,如下所示:PropertiesBasedJdbcDatabaseTester

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

答案 1

我今天遇到了类似的问题(使用v2.2中针对MySQL添加的IDatabaseTester接口),并花了几个小时来撕扯我的头发。OP使用的是 PropertiesBasedJdbcDatabaseTester,而我使用的是它的'父'JdbcDatabaseTester。

DBUnit有一个与此NoSuchColumnException相关的常见问题解答(特定于MySQL),但对我来说,这似乎是一个疏忽,因为它忽略了从接口的getConnection()方法中提取的每个连接都将具有单独的配置。事实上,鉴于我今天看到的各种doco的措辞以及所涉及的类的名称(例如。数据库配置,但每个连接?

无论如何,在设置/拆解(下面的示例)等代码部分中,您甚至没有提供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;
  }
}

最后,所有的错误都消失了。


答案 2

我有理由相信问题源于列作为记录ID。我过去遇到过类似的问题,其中行ID是由SQL Server本机生成的。我现在不在办公桌前,但尝试这个解决方案,看看它是否有帮助:http://old.nabble.com/case-sensitivity-on-tearDown--td22964025.htmluser_id

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

我没有收到任何错误,并且该行已添加到数据库中。

仅供参考,我确实尝试了一个,并且工作正常,也没有错误:-REFRESH

DatabaseOperation.REFRESH.execute(con, dataSet);

我使用的是DBUnit 2.4.8和MySQL 5.1.44。

希望这有帮助。