Перейти к основному содержимому

Руководство по обратным вызовам Flyway

· 5 мин. чтения

1. Введение

Библиотека Flyway позволяет нам создавать версии баз данных, отслеживая изменения, хранящиеся в виде исходного кода SQL. Каждый набор изменений называется миграцией .

Отдельные миграции применяются к базе данных последовательно с помощью набора команд, включающих migrate , clean, info, validate, baseline и repair . Они применяются контролируемым образом в соответствии с текущей версией целевой базы данных.

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

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

2. Сценарии использования

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

  • Перестроение материализованных представлений — нам может понадобиться перестраивать материализованные представления всякий раз, когда мы применяем миграции, влияющие на базовые таблицы этих представлений. Обратные вызовы SQL хорошо подходят для выполнения этого типа логики.
  • Очистка кеша — возможно, у нас есть миграция, которая изменяет данные, которые оказались в кеше. Мы можем использовать обратные вызовы для очистки кешей , чтобы убедиться, что наше приложение извлекает свежие данные из базы данных.
  • Вызов внешней системы — с помощью обратных вызовов мы можем вызывать внешнюю систему с использованием произвольной технологии. Например, мы можем захотеть опубликовать событие, отправить электронное письмо или инициировать перезагрузку сервера.

3. Поддерживаемые обратные вызовы

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

  • События BEFORE_ запускаются до выполнения операции.

  • События AFTER_ запускаются после успешного выполнения операции. Эти афтер -события также имеют несколько более детальных событий:

  • Эквиваленты ERROR запускаются после сбоя операции.

  • События OPERATION_FINISH запускаются после завершения операции.

  • миграция и отмена также имеют событие _EACH, которое запускается для каждой отдельной миграции. Команда migrate и undo содержит эти дополнительные обратные вызовы, потому что выполнение этих команд часто приводит к выполнению множества миграций.

Полный список событий обратного вызова можно найти в классе Event .

Например, событиями обратного вызова для команды очистки являются BEFORE_CLEAN и AFTER_CLEAN . Flyway запускает их непосредственно до и после выполнения чистой команды.

Вспоминая то, что мы обсуждали во введении, доступны следующие команды: migrate , clean, info, validate, baseline и repair .

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

4. Зависимости

Чтобы увидеть, как обратные вызовы работают на практике, давайте рассмотрим простой пример. Мы можем начать работу с нашим примером, объявив flyway-core как зависимость в нашем pom.xml :

<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>8.0.0</version>
</dependency>

Последние версии flyway-core мы можем найти на Maven Central .

5. Обратные вызовы

Flyway позволяет нам создавать обратные вызовы, используя два разных подхода: Java или SQL. Первый является наиболее гибким. Это дает нам свободу выполнять произвольный код.

Последний позволяет нам напрямую взаимодействовать с базой данных.

5.1. Обратные вызовы Java

Контракт Java API определяется в интерфейсе обратного вызова .

В самом простом случае для создания пользовательского обратного вызова нам нужно реализовать интерфейс обратного вызова , как в нашем ExampleFlywayCallback:

public class ExampleFlywayCallback implements Callback {

private final Log log = LogFactory.getLog(getClass());

@Override
public boolean supports(Event event, Context context) {
return event == Event.AFTER_EACH_MIGRATE;
}

@Override
public boolean canHandleInTransaction(Event event, Context context) {
return true;
}

@Override
public void handle(Event event, Context context) {
if (event == Event.AFTER_EACH_MIGRATE) {
log.info("> afterEachMigrate");
}
}

@Override
public String getCallbackName() {
return ExampleFlywayCallback.class.getSimpleName();
}
}

5.2. Обратные вызовы SQL

Контракт обратного вызова SQL определяется с помощью файлов с определенными именами, содержащихся в каталогах, настроенных как местоположения . Flyway будет искать в своих настроенных местоположениях файлы обратного вызова SQL и выполнять их соответствующим образом.

Например, файл с именем beforeEachMigrate.sql в каталоге, сконфигурированном как расположение , будет запускаться перед каждым сценарием миграции во время выполнения команды migrate .

6. Конфигурация и выполнение

В следующем примере мы настраиваем наш обратный вызов Java и указываем два местоположения сценария SQL: одно, содержащее наши миграции, и другое, содержащее обратные вызовы SQL.

Нет необходимости настраивать отдельные местоположения для миграций и обратных вызовов SQL, но мы настроили их таким образом в нашем примере, чтобы продемонстрировать, как их можно хранить отдельно:

@Test
public void migrateWithSqlAndJavaCallbacks() {
Flyway flyway = Flyway.configure()
.dataSource(dataSource)
.locations("db/migration", "db/callbacks")
.callbacks(new ExampleFlywayCallback())
.load();
flyway.migrate();
}

Если мы определим beforeEachMigrate как в Java, так и в SQL, полезно знать, что обратный вызов Java будет выполнен первым, а сразу после него будет выполнен обратный вызов SQL.

Это можно увидеть на выходе из приведенного выше теста:

21:50:45.677 [main] INFO  c.b.f.FlywayApplicationUnitTest - > migrateWithSqlAndJavaCallbacks
21:50:45.848 [main] INFO o.f.c.i.license.VersionPrinter - Flyway Community Edition 8.0.0 by Redgate
21:50:45.849 [main] INFO o.f.c.i.d.base.BaseDatabaseType - Database: jdbc:h2:mem:DATABASE (H2 1.4)
21:50:45.938 [main] INFO o.f.core.internal.command.DbValidate - Successfully validated 2 migrations (execution time 00:00.021s)
21:50:45.951 [main] INFO o.f.c.i.s.JdbcTableSchemaHistory - Creating Schema History table "PUBLIC"."flyway_schema_history" ...
21:50:46.003 [main] INFO o.f.c.i.c.SqlScriptCallbackFactory - Executing SQL callback: beforeMigrate -
21:50:46.015 [main] INFO o.f.core.internal.command.DbMigrate - Current version of schema "PUBLIC": << Empty Schema >>
21:50:46.023 [main] INFO o.f.c.i.c.SqlScriptCallbackFactory - Executing SQL callback: beforeEachMigrate -
21:50:46.024 [main] INFO o.f.core.internal.command.DbMigrate - Migrating schema "PUBLIC" to version "1.0 - add table one"
21:50:46.025 [main] INFO c.b.f.ExampleFlywayCallback - > afterEachMigrate
21:50:46.046 [main] INFO o.f.c.i.c.SqlScriptCallbackFactory - Executing SQL callback: beforeEachMigrate -
21:50:46.046 [main] INFO o.f.core.internal.command.DbMigrate - Migrating schema "PUBLIC" to version "1.1 - add table two"
21:50:46.047 [main] INFO c.b.f.ExampleFlywayCallback - > afterEachMigrate
21:50:46.067 [main] INFO o.f.core.internal.command.DbMigrate - Successfully applied 2 migrations to schema "PUBLIC", now at version v1.1 (execution time 00:00.060s)

7. Заключение

В этой статье мы рассмотрели, как можно использовать механизм обратного вызова Flyway как в Java, так и в SQL. Мы рассмотрели возможные варианты использования и подробно описали пример.

Как всегда, весь исходный код можно найти на GitHub .