org.dbunit.dataset.NoSuchTableException: не удалось найти таблицу 'xxx' в схеме 'null'
Я знаю, что здесь обсуждались дискуссии. Я прочитал большинство из них, но я не могу найти решение своей проблемы.
Я настроил спящий и весенний. Я делаю 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)
У меня есть все файлы отображения гибернации, и база данных уже настроена без данных. Забавная вещь (или раздражающая вещь в зависимости от того, как вы на это смотрите) заключается в том, что если я изменю порядок таблиц в наборе данных, исключение missingtableexception будет жаловаться на другую таблицу... либо на пользователя, на резервирование или на статус.
Любые предложения о том, что я могу делать не так?
8 ответов
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.
Я также сталкивался с той же самой ошибкой, и принятое исправление выше не исправило мои проблемы. Однако мне удалось найти решение.
Моя установка состояла из 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.
Удалите первую строку в файле 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");
Вы создали таблицы базы данных в вашей базе данных?
dbunit
не сделает это за вас, потому что не знает предполагаемой структуры базы данных. Однако вы можете попросить Hibernat сделать это. Использовать hbm2ddl
флаг, например:
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
Я не смог найти основную документацию для флага, но если бы вы ее искали, вы бы получили много результатов, в т.ч. http://docs.jboss.org/ejb3/docs/reference/build/reference/en/html/entityconfig.html
Вы можете быть заинтересованы в этом. Я также обнаружил эту ошибку и, переименовав мою таблицу в hibernate.cfg.xml из "message" в "MESSAGE", смог найти схему.
Дайте мне знать, если это работает и для вас.
Я столкнулся с той же ошибкой, и моя сущность была настроена в hibernate.cfg.xml, и я использовал hbm2ddl для генерации таблиц, поэтому я нашел и обнаружил, что мое сопоставление сущностей содержит поле с именем "POSITION", которое является зарезервированным термином, Когда я изменил его на "POS", таблица была сгенерирована правильно.
Вы можете проверить, генерируется ли ваша таблица, отлаживая итерацию resultSet в
org.dbunit.database.DatabaseDataSet.initialize().
Для меня эта проблема возникла, когда я переименовал и удалил несколько баз данных в схеме, и DBUnit все равно пытался получить к ним доступ (??), но на самом деле он отсутствовал, а также в наборах данных.
для меня помог этот параметр:
@DataSet(..., useSequenceFiltering = false, ...)
или в более общем виде:
@DBUnit(..., disableSequenceFiltering = true, ...)
Из документации dbrider:
- Если это правда, dbunit будет смотреть на ограничения и набор данных, чтобы попытаться определить правильный порядок для операторов SQL. (истина по умолчанию)
PS: возможно, реальная проблема в том, что имена таблиц каким-то образом кэшировались, но я не мог найти, где именно.
Классы 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);
}