Подтвердить что ты не робот

Reset Встроенная база данных H2 периодически

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

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

4b9b3361

Ответ 2

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

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

  • Отключить ограничение целостности
  • Перечислите все таблицы в (ПУБЛИЧНОЙ) схеме (по умолчанию)
  • Усечь все таблицы
  • Перечислите все последовательности в схеме 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();
    }
    

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

Ответ 3

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

Ответ 4

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 (где мы запускаем все необходимые таблицы перед каждым методом тестирования.

Ответ 5

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

  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 между каждым тестом.

Ответ 6

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

spring.jpa.hibernate.ddl-auto=create