简体   繁体   English

DbUnit:NoSuchColumnException和区分大小写

[英]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. 在发布这篇文章之前我搜索了一下,我在dbunit-user档案中查找了一下,还有一些在DbUnit错误列表中查找,但我找不到找到的内容。 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. 我正在使用DbUnit 2.4.8与MySQL 5.1.x在setUp中填充一些JForum表。 The issue is first appearing on jforum_users table created by this script 问题首先出现在此脚本创建的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

Executing REFRESH as database setup operation the following exception is raised. 执行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)

I looked in AbstractTableMetaData.java sources and nothing seems -statically- wrong. 我查看了AbstractTableMetaData.java源代码,似乎没有什么 - 似乎是错误的。 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 最后@limc回答后编辑

I'm using a PropertiesBasedJdbcDatabaseTester to configure my DbUnit env, as follow: 我正在使用PropertiesBasedJdbcDatabaseTester来配置我的DbUnit env,如下所示:

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

I had a similar problem to this today (using the IDatabaseTester interface added in v2.2 against MySQL) and spent several hours tearing my hair out over it. 今天我遇到了类似的问题(使用v2.2中针对MySQL添加的IDatabaseTester接口)并花了几个小时撕掉我的头发。 The OP is using a PropertiesBasedJdbcDatabaseTester, whilst I was using its 'parent' JdbcDatabaseTester. OP正在使用PropertiesBasedJdbcDatabaseTester,而我正在使用其“父”JdbcDatabaseTester。

DBUnit has a FAQ answer related to this NoSuchColumnException (specific to MySQL) but it looks like an oversight to me that it neglects to mention that each connection drawn from the interface's getConnection() method will have separate config. DBUnit有一个与这个NoSuchColumnException相关的FAQ答案 (特定于MySQL),但对我来说这似乎是疏忽,它忽略了从接口的getConnection()方法中提取的每个连接将具有单独的配置。 In fact I'd go so far as to call it bug given the wording of the various bits of doco I looked at today and the names of the classes involved (eg. DatabaseConfig, yet per Connection?). 事实上,考虑到我今天看到的各种doco的措辞和所涉及的类的名称(例如,DatabaseConfig,但是每个连接?),我甚至会把它称为bug。

Anyway, in sections of code like setup/teardown (example below) you don't even provide the Connection object so there's no way I could see to set the config in there. 无论如何,在诸如setup / teardown(下面的示例)之类的代码段中,你甚至都没有提供Connection对象,所以我无法在那里看到设置配置。

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

In the end I just extended JdbcDatabaseTester to @Override the getConnection() method and inject the configuration specific to MySQL each time: 最后,我只是将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;
  }
}

And finally all the errors went away. 最后所有的错误都消失了。

I have reason to believe the problem stemmed from user_id column as the record ID. 我有理由相信问题源于user_id列作为记录ID。 I have similar problem in the past where the row ID is generated natively by SQL Server. 我在过去有类似的问题,其中行ID是由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 我现在不在我的办公桌,但尝试这个解决方案,看它是否有帮助: http//old.nabble.com/case-sensitivity-on-tearDown--td22964025.html

UPDATE - 02-03-11 更新 - 02-03-11

I have a working solution here. 我这里有一个有效的解决方案。 Here's my test code:- 这是我的测试代码: -

MySQL Script 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 Test File dbunit-test.xml测试文件

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

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

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

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:- 仅供参考,我确实尝试过REFRESH并且工作正常而且没有错误: -

DatabaseOperation.REFRESH.execute(con, dataSet);

I'm using DBUnit 2.4.8 and MySQL 5.1.44. 我正在使用DBUnit 2.4.8和MySQL 5.1.44。

Hope this helps. 希望这可以帮助。

I came here looking for an answer to this problem. 我来这里寻找这个问题的答案。 For me the problem was the Hibernate Naming Strategy. 对我来说问题是Hibernate命名策略。 I realised this is the problem as show_sql was true in the Spring's application.properties: 我意识到这是问题,因为show_sql在Spring的application.properties中是真的:

spring.jpa.show-sql=true

I could see the generated table SQL and the field name was 'FACT_NUMBER' instead of 'factNumber' I had in my dbunit's xml. 我可以看到生成的表SQL和字段名称是'FACT_NUMBER'而不是我在dbunit的xml中的'factNumber'。

This was solved by forcing the default naming strategy (ironically the default seems to be org.hibernate.cfg.ImprovedNamingStrategy , which puts in the '_'): 这是通过强制默认命名策略解决的(具有讽刺意味的是默认似乎是org.hibernate.cfg.ImprovedNamingStrategy ,它放入'_'):

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

When I got this error, it was because my schema had a not null constraint on a column, but this column was missing from my datafile. 当我收到此错误时,这是​​因为我的模式对列有一个非空约束,但我的数据文件中缺少此列。

For example, my table had 例如,我的桌子有

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

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

I have a not null constraint on the deleted column and when I run the test, I get the NoSuchColumnException. 我对删除的列有一个非空约束,当我运行测试时,我得到NoSuchColumnException。

When I change the dataset to 当我将数据集更改为

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

I get past the Exception. 我超越了例外。

I was faced with this problem and the reason was that the dtd of my dataset file had a description different of the table where i wanted to insert data. 我遇到了这个问题,原因是我的数据集文件的dtd有一个描述不同于我想要插入数据的表。

So check that your table where you want to insert data has the same columns that your dtd file. 因此,请检查您要插入数据的表与dtd文件的列相同。

when I delete in the dtd file the column that was not in the table where i inserted the data the problem disappeared. 当我在dtd文件中删除不在表中我插入数据的列时,问题就消失了。

Well in my case it was a csv file encoded in UTF-8 with BOM char in the beginning. 在我的情况下,它是一个以UTF-8编码的csv文件,开头有BOM char。 I was using notepad to create csv files. 我正在使用记事本来创建csv文件。 Use notepade++ to avoid saving BOM char. 使用notepade ++可以避免保存BOM char。

I had same problem , then figured I have used different column name in my DB than what I have inside my XML file. 我有同样的问题,然后认为我在我的数据库中使用了不同于我的XML文件中的列名。

I'm sure you got problem in user_id vs USER_ID. 我确定你在user_id和USER_ID中遇到了问题。

I've just stumbled my self over this error message. 我只是偶然发现了这个错误信息。

I had to extend an old piece of code - I needed to add a new column to several tables. 我不得不扩展一段旧代码 - 我需要在几个表中添加一个新列。 In one of my entities I've forgotten to create a setter for this column. 在我的一个实体中,我忘了为这个专栏创建一个setter So you might check your entities if they are "complete". 因此,如果您的实体“完整”,您可以检查它们。

Sometimes it might be as simple as that. 有时它可能就这么简单。

Ok I faced the same trouble and I found the solution, The way we are creating the test data is wrong,for what kind of data set we were using, We were using the xml data set for which following format is correct is you are using the FlatXmlDataSet then there is a different format, for more explanation read in the link provided below. 好的,我遇到了同样的麻烦,我找到了解决方案,我们创建测试数据的方式是错误的,对于我们使用的是什么类型的数据集,我们正在使用xml数据集,以下格式是正确的,你正在使用FlatXmlDataSet然后有一个不同的格式,有关更多解释,请阅读下面提供的链接。 the xml should be in following format. 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>

If you wish to know more go to this link : http://dbunit.sourceforge.net/components.html 如果您想了解更多信息,请访问以下链接: http//dbunit.sourceforge.net/components.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM