Перейти к содержанию

Миграция Flyway с помощью Spring Boot

В этом статье рассмотрим, что такое Flyway и как его настроить при работе с Spring Boot.

Выясним:

  • зачем он вообще нужен в проекте;
  • как быстро настроить Flyway с помощью Spring Boot;
  • как настроить его поведение.

Что такое Flyway и какие проблемы он решает

Flyway – это инструмент управления версиями базы данных. Точно так же, как Git (система контроля версий для кодовой базы), Flyway заботится об управлении схемой базы данных.

Представим, что запустили проект Spring Boot, который взаимодействует с базой данных PostgreSQL. Мы работали самостоятельно, внедряли новые функции, добавляли новые таблицы и много раз меняли схему. В какой-то момент к нашей команде присоединяется новый разработчик, поэтому мы просто экспортируем нашу локальную или удаленную базу данных и отправляем ему скрипт, чтобы он смог настроить локальную среду.

Пока все хорошо, но что будет, если к команде присоединится больше людей? Или хотим создать больше тестовых сред? Конечно, можно сохранять скрипт и обновлять его каждый раз, когда что-то меняем, но это может создать массу проблем, например:

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

Представьте себе работу без Git при сотрудничестве с другими и обмене написанным кодом вручную. Технически выполнимо, но не рекомендуется.

Конечно, Flyway – не единственный инструмент, который можно использовать со Spring Boot, однако с ним легко работать.

Настройка Flyway с помощью Spring Boot

Перейдем к практической части. Если хотите загрузить шаблон для этого руководства, то его можно взять отсюда. Тем не менее, настоятельно рекомендуется настроить проект Spring Boot самостоятельно и выполнить следующие шаги.

Импорт

В качестве первого шага добавим необходимые импорты:

implementation("org.flywaydb:flyway-core:8.5.11")
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
// в качестве альтернативы можно использовать spring-boot-starter-data-jpa

Вышеуказанные зависимости – это минимум, необходимый для работы с Flyway и Spring Boot.

Изменение свойств приложения

В качестве следующего шага необходимо убедиться, что правильно настроили соединение с базой данных. Самый простой способ сделать это – через файл application.yaml (или application.properties):

spring:
  datasource:
    url: "jdbc:postgresql://localhost:5432/your-db-name"
    username: db-username
    password: db-password

По умолчанию Flyway будет использовать источник данных @Primary (который настроили выше).

Добавление каталога миграции

Далее необходимо добавить каталог /db/migration в /resources. Если этого не сделаем и попытаемся запустить приложение, произойдет сбой со следующей ошибкой:

Flyway failed to initialize: none of the following migration scripts locations could be found:
classpath:db/migration

Как настроить каталог, узнаем позже.

Проверка

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

Flyway Community Edition 8.5.11 by Redgate
...
Successfully validated 0 migrations (execution time 00:00.009s)
No migrations found. Are your locations set up correctly?
Creating Schema History table "public"."flyway_schema_history" ...
Schema "public" is up to date. No migration necessary.

Flyway использует эту таблицу для управления версиями и управления примененными, измененными или добавленными скриптами. Подробнее можно узнать в официальной документации.

Добавление миграции

Добавим первый файл миграции с именем V1__Create_User_Table.sql. Это «странное» имя файла является соглашением об именовании Flyway по умолчанию, которое состоит из:

  • префиксаB для базового уровня, R для повторения, U для отмены и V для версии миграции;
  • номера миграции – номер 1 в нашем случае; если хотим, чтобы был 1.1, то должны начать имя с V1_1;
  • двойное подчеркивание – отделяет версию от описания миграции;
  • описание – символы подчеркивания переводятся в пробелы, поэтому миграция будет называться Create User Table.

С учетом сказанного добавим пример SQL-скрипта:

CREATE TABLE IF NOT EXISTS app_user (
id SERIAL NOT NULL PRIMARY KEY,
name TEXT NOT NULL
);

После этого еще раз запустим приложение Spring Boot и проверим логи:

Migrating schema "public" to version "1 - Create User Table"

Как видим, миграция была применена успешно, и в базу данных была добавлена новая таблица.

Настройка Flyway с помощью application.properties

Включение/отключение Flyway

По умолчанию Flyway включен при добавлении в Spring Boot. Если хотим изменить это, можем установить флаг enable:

spring:
  flyway:
    enabled: false

Установка пользовательского каталога миграции

Каталог по умолчанию – /db/migration, но его можно настроить с помощью свойства spring.flyway.locations:

spring:
  flyway:
    locations: "classpath:my-custom-dir,classpath:my-custom-dir-2"

Как видим, можно предоставить несколько каталогов. При работе с Spring Boot classpath означает каталог resources. В качестве альтернативы можно обратиться к любому каталогу в системе, используя файловую систему.

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

/resources
    /my-custom-dir
        V2__one.sql
    /my-custom-dir-2
        V1__one.sql

Эти два каталога обрабатываются точно так же, как и один, и если дважды укажем версию V1, то будет выброшено исключение FlywayException:

Found more than one migration with version 1

Справочник вендоров

Кроме того, Flyway позволяет не только указывать жестко запрограммированные пути, но и использовать заполнитель vendor:

spring:
  flyway:
    locations: "classpath:my-custom-dir/{vendor}"

С приведенной выше конфигурацией Flyway будет искать файлы миграции в каталоге /resources/my-custom-dir/postgresql. Можно найти полный список поддерживаемых вендоров здесь.

Конфигурация Flyway в Java (Kotlin)

Flyway позволяет применять миграции, написанные на Java. При работе с Spring Boot они будут автоматически настроены для любого бина, реализующего интерфейс JavaMigration. Однако этот интерфейс требует реализации нескольких методов, поэтому вместо этого рекомендуется расширить абстрактный класс BaseJavaMigration (этого достаточно в большинстве случаев).

Учитывая это, посмотрим на пример, написанный на Kotlin (который технически не слишком сильно отличается от аналога на Java):

@Component
class V1__Create_User_Table : BaseJavaMigration() {
    override fun migrate(context: Context) {
        val update = context.connection.createStatement()
        update.execute(
            """
            CREATE TABLE IF NOT EXISTS app_user (
                id SERIAL NOT NULL PRIMARY KEY, 
                name TEXT NOT NULL
            );
            """.trimIndent()
        )
    }
}

@Component
class V2__Drop_User_Table : BaseJavaMigration() {
    override fun migrate(context: Context) {
        val update = context.connection.createStatement()
        update.execute("DROP TABLE app_user;")
    }
}

Как видим, единственное, что нужно сделать, это переопределить метод миграции и чтобы имена классов соответствовали соглашению об именовании Flyway по умолчанию.

А можно ли смешивать файлы SQL с конфигурацией Spring Beans? Да, однако необходимо быть очень осторожны с этим.

Заключение

Представленных здесь знаний будет достаточно, чтобы легко включить этот инструмент в любой проект Spring Boot.

Оригинал