DbUnit:NoSuchColumnException 和区分大小写
Posted
技术标签:
【中文标题】DbUnit:NoSuchColumnException 和区分大小写【英文标题】:DbUnit: NoSuchColumnException and case sensitivity 【发布时间】:2011-06-20 02:34:41 【问题描述】:在发布这个之前,我搜索了一下,我在 dbunit-user 中寻找 档案和 DbUnit 错误列表中的一些内容,但我没有找到什么 寻找。 不幸的是,答案here 也没有帮助我。
我使用 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();
【问题讨论】:
一个堆栈溢出我认为 【参考方案1】:我今天遇到了类似的问题(使用 v2.2 中添加的针对 MySQL 的 IDatabaseTester 接口)并花了几个小时来解决这个问题。 OP 使用的是 PropertiesBasedJdbcDatabaseTester,而我使用的是它的“父”JdbcDatabaseTester。
DBUnit 有 a FAQ answer related to this NoSuchColumnException(特定于 MySQL),但它似乎忽略了提到从 interface's getConnection() method 提取的每个连接都将具有单独的配置。实际上,考虑到我今天查看的各种 doco 的措辞以及所涉及的类的名称(例如 DatabaseConfig,但每个连接?),我什至将其称为 bug。
无论如何,在诸如 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;
最后所有的错误都消失了。
【讨论】:
对于 PostgreSQL,必须添加: dbConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory());这将停止有关无法找到的列的错误。【参考方案2】:我有理由相信问题源于 user_id
列作为记录 ID。过去我有类似的问题,行 ID 是由 SQL Server 本地生成的。我现在不在办公桌前,但试试这个解决方案看看是否有帮助:http://old.nabble.com/case-sensitivity-on-tearDown--td22964025.html
更新 - 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);
我正在使用 DBUnit 2.4.8 和 MySQL 5.1.44。
希望这会有所帮助。
【讨论】:
@limc 平面 xml 数据集包含IDataSet dataSet = flatXmlDataSetBuilder.build(new File(testConfDir+"/user/users-and-forums.xml"));
你遇到了什么异常?确保文件路径正确...在您的 File
语句上执行 file.exists()
以确保它是正确的。
FWIW 我遇到了同样的问题,这是由于数据集 xml 文件中的名称不正确引起的。我将属性命名为“employee”而不是“employee_id”。当您必须将大脑从 OOP 切换到 RDBMS 时,就会发生这种情况【参考方案3】:
我来这里是为了寻找这个问题的答案。对我来说,问题是休眠命名策略。我意识到这是问题所在,因为在 Spring 的 application.properties 中 show_sql 是正确的:
spring.jpa.show-sql=true
我可以看到生成的表 SQL 并且字段名称是“FACT_NUMBER”而不是我在 dbunit 的 xml 中的“factNumber”。
这是通过强制使用默认命名策略来解决的(讽刺的是,默认似乎是org.hibernate.cfg.ImprovedNamingStrategy
,它放入了'_'):
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
【讨论】:
【参考方案4】:当我收到此错误时,是因为我的架构对列有非空约束,但我的数据文件中缺少此列。
例如,我的桌子有
<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"/>
我克服了异常。
【讨论】:
【参考方案5】:我遇到了这个问题,原因是我的数据集文件的 dtd 与我要插入数据的表的描述不同。
因此请检查您要插入数据的表是否与您的 dtd 文件具有相同的列。
当我在 dtd 文件中删除不在我插入数据的表中的列时,问题消失了。
【讨论】:
【参考方案6】:在我的例子中,它是一个以 UTF-8 编码的 csv 文件,开头带有 BOM 字符。我正在使用记事本创建 csv 文件。使用 notepad++ 避免保存 BOM 字符。
【讨论】:
【参考方案7】:我遇到了同样的问题,然后发现我在数据库中使用的列名与我在 XML 文件中使用的列名不同。
我确定您在 user_id 与 USER_ID 中遇到了问题。
【讨论】:
【参考方案8】:我刚刚被这个错误消息绊倒了。
我不得不扩展一段旧代码 - 我需要向多个表添加一个新列。在我的一个实体中,我忘记为此列创建 setter。因此,您可以检查您的实体是否“完整”。
有时可能就这么简单。
【讨论】:
【参考方案9】:好的,我遇到了同样的问题,我找到了解决方案,我们创建测试数据的方式是错误的,我们使用的是哪种数据集,我们使用的是以下格式正确的 xml 数据集如果您使用的是 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
【讨论】:
另一种格式是正确的,因为它是 FlatXML,您的格式将是 XML 格式。两者都是正确的,具体取决于您构建数据集的方式。 已更新答案:) :) 更新答案中的链接感谢您的通知(谁曾否决;))以上是关于DbUnit:NoSuchColumnException 和区分大小写的主要内容,如果未能解决你的问题,请参考以下文章