spring org.dbunit.dataset.NoSuchTableException:在架构'null'中未找到表'xxx'

ar7v8xwq  于 2023-02-03  发布在  Spring
关注(0)|答案(8)|浏览(114)

我知道这里有关于dbunit的讨论,我已经读了大部分,但是我似乎找不到解决我问题的方法。
我已经设置好了hib和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)

我已经准备好了所有的HibernateMap文件,并且数据库已经设置好了,没有数据。有趣的事情(或者说烦人的事情取决于你怎么看)是,如果我改变了数据集中表的顺序,MissingTableException会抱怨另一个表......可能是用户、保留或者状态。
有什么建议我可能做错了什么吗?

jaql4c8m

jaql4c8m1#

我也遇到过同样的错误,上面的修复方法并没有解决我的问题,但是我还是找到了解决方案。
我的设置包括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时,如果模式(“public”)不为空,则应该传入它。
其次,我需要DBUnit对数据库表名区分大小写。在我的DBUnit xml文件(“mydbunitdata.xml”)中,表名都是小写的,就像它们在数据库中一样。然而,如果你不告诉DBUnit使用区分大小写的表名,它会寻找Postgres不喜欢的大写表名。因此,我需要在DBUnit中设置区分大小写的特性,这在第59行完成。

vnjpjtjt

vnjpjtjt2#

删除dataset.xml文件中的第一行
<!DOCTYPE dataset>
用这个代替
<?xml version='1.0' encoding='UTF-8'?>
否则DBUnit会尝试从DTD文件中加载数据库表模式,如果没有提供DTD,则它将永远不会匹配任何表。使用纯XML头将导致DBUnit跳过此DTD - table检查,从而引发您所看到的错误。
您还必须执行Grzegorz所做的操作,让hib通过以下命令为您的表执行create-drop操作
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>

configuration.setProperty(Environment.HBM2DDL_AUTO, "create-drop");

jq6vz3qz

jq6vz3qz3#

DBUnit将不会为您创建数据库表,因为它从数据集xml中获得的信息有限,无法创建预期的数据库模式。
当与hib一起使用时,它需要为每个pojo(您试图Map到内存中的测试数据库表)提供正确的hbmMap文件,这些文件最终将用于测试,如果没有Map文件,您将得到org.dbunit.dataset.NoSuchTableException: Did not find table 'xxx' in schema 'yyy'
此外,还需要一个有效的hibernate.cfg.xml,并正确配置了所有的hibMap文件。
通过在属性文件中设置hibernate.hbm2ddl.auto=create-drop属性,可以将数据库创建委托给hib。
这个错误消息有点误导。可能应该包含更多关于缺少HibernateMap文件的信息--但这是DBunit wiki上的讨论。

qhhrdooz

qhhrdooz4#

是否已在数据库中创建数据库表?
dbunit不会为你做这件事,因为它不知道想要的数据库结构。但是你可以让Hibernat来做。使用hbm2ddl标志,例如:

<property name="hibernate.hbm2ddl.auto" value="create-drop"/>

我找不到该标志的主要文档,但如果您搜索它,会得到很多结果,包括http://docs.jboss.org/ejb3/docs/reference/build/reference/en/html/entityconfig.html

ctrmrzij

ctrmrzij5#

您可能对此感兴趣。我也发现了这个错误,通过将hibernate.cfg.xml中的表从“message”重命名为“MESSAGE”,它能够找到模式。
如果你也这样做的话告诉我。

nvbavucw

nvbavucw6#

我遇到了同样的错误,我在hibernate.cfg.xml中配置了实体,并且使用hbm2ddl生成表,所以我进行了搜索,发现实体Map包含一个名为“POSITION”的字段,这是一个保留术语。当我将其更改为“POS”时,正确生成了表。
您可以通过在中调试resultSet迭代来检查是否正在生成表
数据库单元。数据库。数据库数据集。

0h4hbjxa

0h4hbjxa7#

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);
}
pjngdqdw

pjngdqdw8#

对我来说,这个问题出现在我重命名和删除模式中的一些数据库时,DBUnit无论如何都试图访问它(??),但它确实不存在,而且在数据集中也不存在。
这个参数对我有帮助:

@DataSet(..., useSequenceFiltering = false, ...)

或者更一般地说:

@DBUnit(..., disableSequenceFiltering = true, ...)

来自dbrider文件:

  • 如果为true,dbunit将查看约束和数据集,以尝试确定SQL语句的正确顺序。(默认为true)

P.S.:可能,真实的的问题是表名被缓存了,但我找不到确切的位置。

相关问题