org.dbunit.dataset.NoSuchTableException:在架构“null”中找不到表“xxx”
Posted
技术标签:
【中文标题】org.dbunit.dataset.NoSuchTableException:在架构“null”中找不到表“xxx”【英文标题】:org.dbunit.dataset.NoSuchTableException: Did not find table 'xxx' in schema 'null' 【发布时间】:2011-07-01 06:33:53 【问题描述】:我知道这里有关于 dbunit 的讨论。我已经阅读了其中的大部分内容,但似乎找不到解决问题的方法。
我已经设置了hibernate和spring。我正在做 TDD,所以我必须在编写代码之前连接一个适当的 DAO 测试框架。我想到了 Dbunit,我开始设置它。这里是 ma testdataset.xml
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<table name="status">
<column>statusId</column>
<column>status</column>
<row>
<value>0</value>
<value>Available</value>
</row>
</table>
<table name="user">
<column>userId</column>
<column>firstName</column>
<column>lastName</column>
<column>username</column>
<column>password</column>
<column>email</column>
<row>
<value>0</value>
<value>system</value>
<value>admin</value>
<value>admin</value>
<value>admin</value>
<value>admin@ccbs.com</value>
</row>
</table>
<table name="reservation">
<column>reservationId</column>
<column>userId</column>
<column>reservationDate</column>
<column>startDate</column>
<column>endDate</column>
<column>statusId</column>
<row>
<value>0</value>
<value>0</value>
<value>2011-02-20 12:46:00.0</value>
<value>2011-03-01 12:00:00.0</value>
<value>2011-04-01 12:00:00.0</value>
<value>0</value>
</row>
</table>
</dataset>
在我尝试使用加载数据集的基类连接一些代码之前,一切似乎都很好。这是我的代码:
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:test-applicationContext.xml" )
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class BaseContextSensitiveTest
@BeforeClass
public static void setUpDatabase() throws Exception
URL file = getInitalDatasetURL();
testDataset = createDataset(file);
@Before
public void init() throws Exception
log.info("Initializing Data Set");
connection = createDBUnitConnection();
DatabaseOperation.CLEAN_INSERT.execute(connection, testDataset);
private static URL getInitalDatasetURL() throws FileNotFoundException
URL file = ClassLoader.getSystemResource(TEST_DATASET_LOCATION);
if (file == null)
throw new FileNotFoundException("Unable to find '"
+ TEST_DATASET_LOCATION + "' in the classpath");
return file;
private static IDataSet createDataset(URL file) throws IOException,
DataSetException
return new XmlDataSet(file.openStream());
private IDatabaseConnection createDBUnitConnection()
throws DatabaseUnitException, SQLException
Connection connection = getConnection();
IDatabaseConnection dbUnitConn = new DatabaseConnection(connection);
// use the hsql datatypefactory so that boolean properties work
// correctly
DatabaseConfig config = dbUnitConn.getConfig();
config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
new HsqldbDataTypeFactory());
return dbUnitConn;
一旦碰到DatabaseOperation.CLEAN_INSERT.execute(connection, testDataset);
,它就会抛出以下异常:
org.dbunit.dataset.NoSuchTableException: Did not find table 'USER' in schema 'null'
at org.dbunit.database.DatabaseTableMetaData.<init>(DatabaseTableMetaData.java:142)
at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:290)
at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:109)
at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
at com.cottage.test.BaseContextSensitiveTest.init(BaseContextSensitiveTest.java:64)
我已准备好所有休眠映射文件,并且数据库已设置为没有数据。有趣的事情(或恼人的事情取决于你如何看待它)是,如果我更改数据集中表的顺序,missingtableexception 会抱怨另一个表......用户、预订或状态。
关于我可能做错的任何建议?
【问题讨论】:
如果在表名 status 前面加上模式名会发生什么 --> myschema.status ? @Luciano Fiandesio,你的意思是在创建 IDatabaseConnection dbUnitConn = new DatabaseConnection(connection, "SCHEMA?NAME") 时? 不,我的意思是在 xml 数据集文件中我也遇到了同样的错误,上面接受的修复并没有解决我的问题。但是我能够找到解决方案。
我的设置包括 DBUnit(2.4)、EclipseLink(2.1) 作为我的 JPA 提供程序和 Postgres 作为我的后端数据库。此外,在我的场景中,我没有为每次测试运行删除和重新创建表。我的测试数据已经存在。我知道不好的做法,但这更像是一个测试/原型设计场景。下面的代码说明了用于解决我的问题的 DBUnit 配置。
54 // ctx represents a spring context
55 DataSource ds = (DataSource)ctx.getBean("myDatasourceBean");
56 Connection conn = DataSourceUtils.getConnection(ds);
57 IDatabaseConnection dbUnitConn = new DatabaseConnection(conn, "public");
58 DatabaseConfig dbCfg = dbUnitConn.getConfig();
59 dbCfg.setFeature(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES, Boolean.TRUE);
60 IDataSet dataSet = new FlatXmlDataSet(ClassLoader.getSYstemResourceAsStream("mydbunitdata.xml"));
61 DatabaseOperation.REFRESH.execute(dbUnitConn, dataSet);
上面代码中的两件事解决了我的问题。首先,我需要定义 DBUnit 应该使用的模式。这是在上面的第 57 行完成的。设置新的 DatabaseConnection 时,如果 schema("public") 不为 null,则应传入。
其次,我需要 DBUnit 区分数据库表名的大小写。在我的 DBUnit xml 文件(“mydbunitdata.xml”)中,表名都是小写的,就像它们在数据库中一样。但是,如果您不告诉 DBUnit 使用区分大小写的表名,它会查找 Postgres 不喜欢的大写表名。因此我需要在第 59 行设置 DBUnit 中区分大小写的功能。
【讨论】:
我认为区别在于 JPA。我将hibernate与generic-hibernate-DAO结合使用。而且,我没有使用 EclipseLink。 对于 dbunit 2.4.5 及更高版本,有对 postgres 的特定支持,您只需使用以下命令即可获得这些选项: DatabaseConfig dbUnitConConfig = dbUnitCon.getConfig(); dbUnitConConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory()); 对我来说,在DatabaseConnection
构造函数中传递模式名称解决了这个问题,即使我在数据库 URL 本身中指定了它。【参考方案2】:
删除 dataset.xml 文件中的第一行
<!DOCTYPE dataset>
用这个替换它
<?xml version='1.0' encoding='UTF-8'?>
否则 DBUnit 会尝试从 DTD 文件加载 db 表模式,如果没有提供 DTD,它将永远不会匹配任何表。使用纯 xml 标头将导致 DBUnit 跳过此 DTD - 表检查,该检查会引发您看到的错误。
您还必须做 Grzegorz 所做的事情,并通过包含
让 hibernate 为您的表创建删除<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
或
configuration.setProperty(Environment.HBM2DDL_AUTO, "create-drop");
【讨论】:
这就是我所说的,这对我有很大帮助,因为我设置了 create-drop 属性并正确设置了所有内容。在以前的 DBUnit 版本中,当您使用 时,它仍然可以工作。由于我升级了我的 DBUnit(事实上,我从 Unitils 转移到最新版本的 spring-test-dbunit - 我可以推荐它)这不再起作用,所以我正在查看我的问题但找不到原因。所以我可以确认上述修复适用于 spring-test-dbunit 1.1.0 版!【参考方案3】:DBUnit 不会为您创建数据库表,因为它从数据集 xml 中获得的信息有限,无法创建预期的数据库模式。
当与 hibernate 一起使用时,它需要为每个 pojo 提供适当的 hbm 映射文件(您试图映射到内存中的测试数据库表),最终在测试中使用。如果没有映射文件,您将获得org.dbunit.dataset.NoSuchTableException: Did not find table 'xxx' in schema 'yyy'
。
此外,还需要一个有效的 hibernate.cfg.xml,并正确配置了所有的 hibernate 映射文件。
您可以通过在属性文件中设置此属性hibernate.hbm2ddl.auto=create-drop
将数据库创建委托给休眠。
错误信息有点误导。可能应该包含更多关于缺少休眠映射文件的信息——但这是 DBunit wiki 上的讨论。
【讨论】:
【参考方案4】:您是否在数据库中创建了数据库表?
dbunit
不会为你做这件事,因为它不知道预期的数据库结构。但是,您可以要求 Hibernat 执行此操作。使用hbm2ddl
标志,例如:
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
我找不到该标志的主要文档,但如果您搜索它,您会得到很多结果,包括。 http://docs.jboss.org/ejb3/docs/reference/build/reference/en/html/entityconfig.html
【讨论】:
感谢@Grzegorz Oledzki 的快速回复。我在数据库中创建了表。我正在使用 liquibase 进行数据库变更日志管理。 谢谢@Grzegorz Oledzki:你说得对,dbunit 没有在我的数据库中为我创建表。虽然这不是问题,但问题是我忘记将映射文件添加到 hibernate.cfg.xml 文件中——我不好意思承认。但是,我曾要求 hibernate 使用这个 hibernate.hbm2ddl.auto=create-drop 作为我的属性文件中的属性来执行此操作。我不确定我是否应该将您的答案标记为正确答案,尽管它有助于解决问题。我真的很感谢你们的帮助。非常感谢——它现在可以工作了!【参考方案5】:您可能对此感兴趣。我也发现了这个错误,通过将 hibernate.cfg.xml 中的表从“消息”重命名为“消息”,它能够找到架构。
让我知道这是否也适合你。
【讨论】:
【参考方案6】:我遇到了同样的错误,我在 hibernate.cfg.xml 中配置了我的实体,并且我正在使用 hbm2ddl 生成表,所以我搜索并发现我的实体映射包含一个名为“POSITION”的字段,它是一个保留期限。当我将其更改为“POS”时,表格已正确生成。
您可以通过调试中的resultSet迭代来检查您的表是否正在生成
org.dbunit.database.DatabaseDataSet.initialize()。
【讨论】:
【参考方案7】:DbUnit 类从数据库中获取默认架构,如果您要使用的架构不是默认架构,则需要在 .xml 文件中设置所需架构并启用其他架构的识别选项,请参阅解决方案以下。我创造了它。
Example.xml - 多个架构
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<SCHEMA1.NAME_TABLE id="5" userName="1" />
<SCHEMA2.NAME_TABLE id="2" roleName="1" />
<dataset>
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<PEOPLE.USER id="5" userName="1" />
<FUNCTIONS.ROLE id="2" roleName="1" />
<dataset>
测试类
@Before
public void initialize() throws Exception
//Insert data into database
DatabaseOperation.CLEAN_INSERT.execute(getConnection(), getDataSet());
@After
public void cleanup() throws Exception
//Clean up the database
DatabaseOperation.DELETE_ALL.execute(getConnection(), getDataSet());
System.out.println("DELETADO COM SUCESSO!");
private IDatabaseConnection getConnection() throws Exception
// Get the database connection
Connection con = dataSource.getConnection();
DatabaseMetaData databaseMetaData = con.getMetaData();
DatabaseConnection connection = new DatabaseConnection(con,databaseMetaData.getUserName().toUpperCase());
//Allow multiple schemas to be used
connection.getConfig().setFeature(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true);
return connection;
private IDataSet getDataSet() throws Exception
//Get file to insert
File file = new File("src/test/resources/Example.xml");
return new FlatXmlDataSet(file);
【讨论】:
以上是关于org.dbunit.dataset.NoSuchTableException:在架构“null”中找不到表“xxx”的主要内容,如果未能解决你的问题,请参考以下文章