Ответ 1
H2 поддерживает специальный оператор SQL для отбрасывания всех объектов:
DROP ALL OBJECTS [DELETE FILES]
Если вы не хотите удалять все таблицы, вы можете использовать усеченную таблицу:
TRUNCATE TABLE
Я создаю новую версию своего приложения на демо-сервере и хотел бы найти способ ежедневной перезагрузки базы данных. Наверное, у меня всегда может быть выполнение задания cron и создание запросов, но я ищу более чистый подход. Я пробовал использовать специальный блок постоянного присутствия с методом drop-create, но он не работает, так как система часто и часто отключается от сервера (по запросу).
Есть ли лучший подход?
H2 поддерживает специальный оператор SQL для отбрасывания всех объектов:
DROP ALL OBJECTS [DELETE FILES]
Если вы не хотите удалять все таблицы, вы можете использовать усеченную таблицу:
TRUNCATE TABLE
Поскольку этот ответ является первым результатом Google для "сброса базы данных H2", я публикую свое решение ниже:
После каждого JUnit @tests:
Включите ограничения.
@After
public void tearDown() {
try {
clearDatabase();
} catch (Exception e) {
Fail.fail(e.getMessage());
}
}
public void clearDatabase() throws SQLException {
Connection c = datasource.getConnection();
Statement s = c.createStatement();
// Disable FK
s.execute("SET REFERENTIAL_INTEGRITY FALSE");
// Find all tables and truncate them
Set<String> tables = new HashSet<String>();
ResultSet rs = s.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='PUBLIC'");
while (rs.next()) {
tables.add(rs.getString(1));
}
rs.close();
for (String table : tables) {
s.executeUpdate("TRUNCATE TABLE " + table);
}
// Idem for sequences
Set<String> sequences = new HashSet<String>();
rs = s.executeQuery("SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.SEQUENCES WHERE SEQUENCE_SCHEMA='PUBLIC'");
while (rs.next()) {
sequences.add(rs.getString(1));
}
rs.close();
for (String seq : sequences) {
s.executeUpdate("ALTER SEQUENCE " + seq + " RESTART WITH 1");
}
// Enable FK
s.execute("SET REFERENTIAL_INTEGRITY TRUE");
s.close();
c.close();
}
Другим решением было бы воссоздать базу данных в начале каждого теста. Но это может быть слишком долго в случае большой базы данных.
Команда: SHUTDOWN
Вы можете выполнить его с помощью RunScript.execute(jdbc_url, user, password, "classpath: shutdown.sql", "UTF8", false);
Я запускаю его каждый раз, когда набор тестов завершается с помощью @AfterClass
Thre - специальный синтаксис в Spring для обработки базы данных в модульных тестах
@Sql(scripts = "classpath:drop_all.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
@Sql(scripts = {"classpath:create.sql", "classpath:init.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public class UnitTest {}
В этом примере мы выполняем drop_all.sql script (где мы отбрасываем все необходимые таблицы) после каждого тестового метода. В этом примере мы выполняем create.sql script (где мы создаем все необходимые таблицы) и init.sql script (где мы запускаем все необходимые таблицы перед каждым методом тестирования.
Если вы используете весеннюю загрузку, см. этот вопрос о стеке потока
Настройте ваш источник данных. У меня нет особого закрытия при выходе.
источник данных: driverClassName: org.h2.Driver url: "jdbc: h2: mem: psptrx"
Spring boot @DirtiesContext аннотация
@DirtiesContext (classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
Используйте @Before для инициализации каждого теста.
@DirtiesContext вызовет сброс контекста h2 между каждым тестом.
Вы можете написать в application.properties следующий код для сброса таблиц, загруженных JPA:
spring.jpa.hibernate.ddl-auto=create