Spring Boot + Hibernate + Flyway: не запускайте миграции на новую базу данных - PullRequest
0 голосов
/ 31 августа 2018

Я использую Flyway для обновления схемы БД. В настоящее время самая последняя версия схемы - 3 (последний файл миграции называется V3__postgres.sql).

Если я запускаю приложение в базе данных, имеющей более старую версию схемы, Flyway выполняет сценарии обновления, как ожидается. Однако, если я запускаю приложение в новой (пустой) базе данных, flyway пытается выполнить сценарии обновления, но не находит таблиц (потому что Hibernate еще не создал их), и приложение завершает работу при ошибке.

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

Если я правильно понимаю, я смогу использовать для этого параметр flyway.baseline-version. Моя теория состоит в том, что если Flyway не находит таблицу schema_version, он должен создать ее и вставить запись о том, что БД имеет версию 3. Но даже если я установлю flyway.baseline-version=3, Flyway все равно выполнит сценарии. Я также пытался установить параметр flyway.baseline-on-migrate=true и их различные комбинации, но не смог заставить его работать.

Правильно ли я понимаю параметр baseline-version или я что-то упустил?

Примечание: Мне известно, что после Spring Boot 2 пространство имен параметров изменилось на spring.flyway.*, но я использую Spring Boot 1, так что это не проблема.

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Решено: я создал пользовательский компонент FlywayMigrationStrategy, где я вручную проверяю, был ли Flyway уже введен в базу данных (проверяя, существует ли таблица миграции). Если нет, я запускаю команду baseline. Затем я вызываю команду migrate как обычно.

Вот конфигурация Spring Boot:

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FlywayConfig {

    @Autowired
    private DataSource dataSource;

    @Value("${flyway.table}")
    private String flywayTableName;

    @Value("${flyway.baselineVersionAsString}")
    private String baselineVersion;

    @Bean
    public FlywayMigrationStrategy flywayMigrationStrategy() {
        return flyway -> {
            if (!isFlywayInitialized()) {
                flyway.setBaselineVersionAsString(baselineVersion);
                flyway.baseline();
            }
            flyway.migrate();
        };
    }

    private boolean isFlywayInitialized() {

        try (Connection connection = dataSource.getConnection()) {
            DatabaseMetaData metadata = connection.getMetaData();
            ResultSet result = metadata.getTables(null, null, flywayTableName, null);
            return result.next();
        } catch (SQLException e) {
            throw new RuntimeException("Failed to check if Flyway is initialized", e);
        }
    }

}
0 голосов
/ 04 сентября 2018

Как уже упоминалось в комментариях, flyway и hibernate не должны использоваться вместе для обновления схемы, но это не означает, что вы вообще не можете использовать Hibernate для поддержки своей схемы.

Базовый : Эта функция определенно не предназначена для предотвращения выполнения миграции на пустых базах данных. Это лучше использовать, когда ваша база данных уже существует (то есть в ней уже есть таблицы и данные, и вы хотите сохранить эти данные). Для пустых баз это бесполезно.

Пример: Предположим, у вас есть база данных, сгенерированная с помощью двух скриптов:

V1__create_tables.sql
V2__create_constraints.sql

Теперь вы хотите управлять дальнейшими обновлениями схемы с помощью flyway:

V3__First_update.sql
V4__Second_update.sql

V2 - это ваша базовая линия, означающая, что миграция базы данных не будет выполнять миграции V1 и V2, поскольку они уже существуют.

Если вы хотите объединить Spring Boot + Hibernate + Flyway :

Теперь вы готовы использовать Hibernate и Flyway для каждой предстоящей модификации схемы. Предположим, вы только что обновили свою модель:

  • Используйте Hibernate SchemaGenerator для генерации того же большого SQL-файла, назовем его generator-output.sql.
  • Проведите параллельное сравнение V1__initial_schema.sql и generator-output.sql. Это поможет вам определить различия между двумя файлами. Основываясь на этих различиях, вы можете создать новый файл миграции, назовем его V2__update.sql.
  • Сделайте flyway migrate в вашей базе данных.
...