org.dbunit.dataset.NoSuchTableException: не удалось найти таблицу 'xxx' в схеме 'null' - PullRequest
8 голосов
/ 21 февраля 2011

Я знаю, что здесь обсуждались вопросы, связанные с dbunit. Я прочитал большинство из них, но не могу найти решение своей проблемы.

Я установил спящий режим и весну. Я делаю TDD, поэтому мне пришлось подключить надлежащую среду тестирования DAO перед написанием кода. Dbunit пришел на ум, и я приступил к настройке. Вот моя 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)

У меня есть все файлы отображения гибернации, и база данных уже настроена без данных. Забавная вещь (или раздражающая вещь в зависимости от того, как вы на это смотрите) заключается в том, что, если я изменяю порядок таблиц в наборе данных, исключение losttableexception будет жаловаться на другую таблицу ... либо на пользователя, на резервирование или на статус.

Любые предложения о том, что я могу делать не так?

Ответы [ 6 ]

12 голосов
/ 23 сентября 2011

Я также сталкивался с этой же ошибкой, и принятое исправление выше не решило мои проблемы. Однако мне удалось найти решение.

Моя установка состояла из 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.

8 голосов
/ 06 мая 2011

удалить первую строку в файле dataset.xml

<!DOCTYPE dataset>

и замените его на

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

в противном случае DBUnit пытается загрузить схему таблиц БД из файла DTD, и если DTD не указан, он никогда не будет совпадать ни с одной таблицей. Использование простого заголовка xml приведет к тому, что DBUnit пропустит эту проверку DTD - таблицы, которая выдает ошибку, которую вы видите.

Вы также должны сделать то же, что сделал Гжегож, и чтобы hibernate сделал create-drop для ваших таблиц, включив

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

или

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

8 голосов
/ 21 февраля 2011

DBUnit не будет создавать таблицы базы данных для вас, поскольку он содержит ограниченную информацию из набора данных xml для создания предполагаемой схемы базы данных.

При использовании в тандеме с hibernate для каждого pojo (который вы пытаетесь сопоставить с таблицами базы данных тестов в памяти) потребуются надлежащие файлы отображения hbm, которые в конечном итоге используются в тестах.Без файлов сопоставления вы получите org.dbunit.dataset.NoSuchTableException: Did not find table 'xxx' in schema 'yyy'.

. Также требуется действительный файл hibernate.cfg.xml, правильно настроенный для всех файлов сопоставления гибернации.

Вы можете делегироватьсоздание базы данных в спящем режиме, установив это свойство hibernate.hbm2ddl.auto=create-drop в файле свойств.

Сообщение об ошибке немного вводит в заблуждение.Вероятно, должно содержать больше информации о влиянии отсутствующих файлов отображения гибернации - но это обсуждение на вики DBunit.

2 голосов
/ 21 февраля 2011

Вы создали таблицы базы данных в своей базе данных?

dbunit не сделает это за вас, потому что она не знает предполагаемую структуру базы данных.Однако вы можете попросить Hibernat сделать это.Используйте флаг hbm2ddl, например:

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

Я не смог найти основную документацию для флага, но если бы вы его искали, вы бы получили много результатов, в т.ч.http://docs.jboss.org/ejb3/docs/reference/build/reference/en/html/entityconfig.html

1 голос
/ 12 июля 2011

Вас это может заинтересовать.Я также обнаружил эту ошибку и, переименовав мою таблицу в hibernate.cfg.xml из «message» в «MESSAGE», смог найти схему.

Дайте мне знать, если это работает и у вас.

0 голосов
/ 03 октября 2014

Я столкнулся с той же ошибкой, и моя сущность была сконфигурирована в hibernate.cfg.xml, и я использовал hbm2ddl для генерации таблиц, поэтому я искал и обнаружил, что мое сопоставление сущностей содержит поле с именем "POSITION", которое зарезервированный термин. Когда я изменил его на «POS», таблица была сгенерирована правильно.

Вы можете проверить, генерируется ли ваша таблица, отлаживая итерацию resultSet в

org.dbunit.database.DatabaseDataSet.initialize ().

...