Периодически сбрасывать встроенную базу данных H2 - PullRequest
40 голосов
/ 15 декабря 2011

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

Есть ли лучший подход?

Ответы [ 6 ]

69 голосов
/ 16 декабря 2011

H2 поддерживает специальный оператор SQL для удаления всех объектов :

DROP ALL OBJECTS [DELETE FILES]

Если вы не хотите удалять все таблицы, вы можете использовать усеченную таблицу:

TRUNCATE TABLE 
20 голосов
/ 11 мая 2016

Поскольку этот ответ является первым результатом Google для "сброса базы данных H2", я публикую свое решение ниже:

После каждого теста JUnit @ :

  • Отключить ограничение целостности
  • Список всех таблиц в схеме PUBLIC (по умолчанию)
  • Усечение всех таблиц
  • Список всех последовательностей в схеме PUBLIC (по умолчанию)
  • Сброс всех последовательностей
  • Повторное включение ограничений.

    @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();
    }
    

Другим решением будет воссоздание базы данных в начале каждого теста.Но это может быть слишком долго в случае большой базы данных.

2 голосов
/ 04 апреля 2018

Если вы используете пружинную загрузку, посмотрите этот stackoverflow вопрос

  1. Настройка источника данных. У меня нет особого закрытия при выходе.

    Источник данных: driverClassName: org.h2.Driver url: "jdbc: h2: mem: psptrx"

  2. Spring boot @DirtiesContext аннотация

    @ DirtiesContext (classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)

  3. Используйте @Before для инициализации каждого теста.

@DirtiesContext будет вызывать сброс контекста h2 между каждым тестом.

2 голосов
/ 08 апреля 2017

Это специальный синтаксис в 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 (где мы отбрасываем все необходимые таблицы) после каждый метод испытаний.В этом примере мы выполняем сценарий create.sql (где мы создаем все необходимые таблицы) и сценарий init.sql (где мы инициируем все необходимые таблицы до каждого тестаспособ.

2 голосов
/ 19 марта 2013

Команда: SHUTDOWN
Вы можете выполнить его с помощью RunScript.execute (jdbc_url, пользователь, пароль, "classpath: shutdown.sql", "UTF8", false);
Я запускаю его каждый раз, когда завершается набор тестов с использованием @ AfterClass

0 голосов
/ 21 июля 2018

вы можете написать в application.properties следующий код для сброса ваших таблиц, которые загружены JPA:

spring.jpa.hibernate.ddl-auto=create
...