Java for Beginner
678 subscribers
562 photos
156 videos
12 files
862 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Введение в Flyway

Flyway представляет собой специализированный инструмент управления миграциями баз данных, реализующий принцип "Database-as-Code". Его фундаментальная задача заключается в обеспечении контролируемого и воспроизводимого процесса эволюции схемы базы данных через систему версионированных изменений.

Ключевые функциональные аспекты:
Декларативное управление схемой - все изменения БД описываются в виде отдельных скриптов
Детерминированность применения - каждая миграция имеет строгую версионную привязку
Атомарность изменений - миграции применяются как единое целое (транзакционно)
Историчность - полный аудит всех выполненных изменений


Сравнение с Liquibase

Принципиальные различия между Flyway и Liquibase проявляются в нескольких аспектах:

Архитектурный подход
Flyway придерживается парадигмы "SQL-первым", где основным носителем изменений являются нативные SQL-скрипты. Liquibase предлагает абстрактный DSL (XML/YAML/JSON) для описания изменений, который затем транслируется в SQL.

Механизм откатов
В Flyway стратегия откатов реализована через создание новых миграционных скриптов с обратными изменениями. Liquibase предоставляет встроенный механизм описания операций отката непосредственно в changeSet.

Сложность и гибкость
Flyway демонстрирует минималистичный подход с низким порогом вхождения. Liquibase предлагает более богатый функционал за счет усложненной модели конфигурации.

Интеграционные возможности
Оба инструмента имеют глубокую интеграцию с экосистемой Java, но Flyway чаще выбирают для Spring Boot-проектов благодаря более простой автоконфигурации.


Базовые концепции

Модель миграций

Flyway оперирует двумя фундаментальными типами миграций:

Версионные миграции (префикс V)
Линейно упорядоченные изменения схемы
Неизменяемые после применения


Пример именования: V2__Add_email_column.sql

Содержимое SQL-скрипта:

ALTER TABLE users ADD COLUMN email VARCHAR(255);


Повторяемые миграции (префикс R)
Перезаписываемые скрипты
Применяются при изменении контрольной суммы


Пример: R__Update_report_views.sql


Механизм контроля версий

Система использует служебную таблицу flyway_schema_history, содержащую:
Точную версию каждой примененной миграции
Контрольную сумму скрипта
Временные метки выполнения
Статус операции


Жизненный цикл изменений

Типичный workflow включает:
Инициализацию схемы (baseline)
Валидацию существующих миграций
Применение новых изменений (migrate)
При необходимости - очистку (clean) и повторное развертывание



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

Flyway обеспечивает совместимость с большинством современных реляционных СУБД:
PostgreSQL (полная поддержка, включая расширения)
MySQL/MariaDB (включая специфичные движки хранения)
Oracle (с учетом особенностей PL/SQL)
SQL Server (включая Azure SQL)
Встраиваемые БД (H2, SQLite)
Для NoSQL-систем (MongoDB) требуется использование коммерческой версии
Flyway. Важно отметить, что некоторые специфические функции СУБД могут требовать особого подхода при миграциях.


Типовые сценарии использования

Разработка - синхронизация схемы между средами
Тестирование - подготовка изолированных тестовых БД
Развертывание - автоматизация деплоя в production
Анализ - отслеживание истории изменений схемы


#Java #middle #Flyway
Настройка и базовые команды Flyway

1. Конфигурация Flyway

1.1. Файл flyway.conf
Основной файл конфигурации Flyway. Располагается в корне проекта или в директории conf.

Пример содержимого:
# Подключение к БД
flyway.url=jdbc:postgresql://localhost:5432/mydb
flyway.user=admin
flyway.password=secret

# Директории с миграциями
flyway.locations=classpath:db/migration,filesystem:/opt/migrations

# Дополнительные настройки
flyway.schemas=public
flyway.baselineOnMigrate=true


Ключевые параметры:
flyway.url — JDBC-URL базы данных (формат зависит от СУБД).

flyway.locations — пути к миграциям:
classpath: — поиск в ресурсах проекта (например, src/main/resources/db/migration).
filesystem: — абсолютный путь на диске.
flyway.baselineOnMigrate — инициализация существующей БД (без таблицы flyway_schema_history).

1.2. Параметры командной строки

Настройки можно переопределять через аргументы:
flyway -url=jdbc:postgresql://localhost:5432/mydb \
-user=admin \
-password=secret \
-locations=classpath:db/migration \
migrate
Важно: Параметры из командной строки имеют приоритет над flyway.conf.


2. Основные CLI-команды

2.1. flyway migrate

Применяет все невыполненные миграции.

Процесс:
Проверяет таблицу flyway_schema_history.
Находит скрипты, которых нет в истории.
Выполняет их в порядке версий (например, V1__... перед V2__...).


Пример:
flyway migrate


2.2. flyway info

Показывает текущее состояние БД:
Какие миграции применены.
Какие ожидают выполнения.
Статус (Success, Pending, Failed).


Вывод:
+-----------+---------+---------------------+------+---------------------+---------+
| Version | Description | Installed on | State | Type | Checksum |
+-----------+---------+---------------------+------+---------------------+---------+
| 1 | Create users | 2024-03-15 10:00 | Done | SQL | 1234abcd |
| 2 | Add email | Pending | | SQL | 5678efgh |
+-----------+---------+---------------------+------+---------------------+---------+


2.3. flyway validate

Проверяет:
Целостность скриптов (не изменены ли уже примененные).
Корректность именования.


Ошибка:
Validation failed: Detected applied migration not resolved locally: 1
Причина: Локальный скрипт V1__... был изменен после применения к БД.


2.4. flyway clean

Удаляет все объекты БД (таблицы, процедуры), включая flyway_schema_history.
Опасность: Необратимая операция. Используется только в dev-среде.

flyway clean


3. Форматы миграций

3.1. SQL-миграции

Стандартный подход. Скрипты с расширением .sql в директории db/migration.

Пример (V1__Create_users.sql):
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL
);

INSERT INTO users (id, username) VALUES (1, 'admin');


3.2. Java-миграции

Для сложной логики (например, условные операции).


Шаги:
Создайте класс в проекте:
public class V2__InsertTestData implements JdbcMigration {
public void migrate(Connection connection) throws Exception {
try (Statement stmt = connection.createStatement()) {
stmt.execute("INSERT INTO users (username) VALUES ('test')");
}
}
}


Укажите путь к Java-классам в flyway.locations:
flyway.locations=classpath:db/migration,classpath:com/example/migrations


3.3. Callbacks (SQL-хуки)

Скрипты, выполняемые до/после событий Flyway.

Пример (beforeMigrate.sql):
-- Выполняется перед началом миграций
CREATE SCHEMA IF NOT EXISTS audit;


Поддерживаемые события:

beforeMigrate, afterMigrate.
beforeClean, afterClean.


Директория:
db/
migration/
V1__...sql
callback/
beforeMigrate.sql


4. Важные замечания

Именование файлов:
Регистрозависимо (V1__test.sql ≠ v1__test.sql).
Разделитель — двойное подчеркивание (__).


Порядок выполнения:
Сначала V1__..., затем V2__....
R__... выполняются после всех версионных.


Безопасность:

Никогда не изменяйте уже примененные скрипты.
Для отката создавайте новые миграции (например, V3__Drop_table.sql).


#Java #middle #Flyway
Типы миграций и версионирование в Flyway

1. Структура SQL-миграций

Flyway классифицирует SQL-миграции по префиксам в именах файлов, определяя их поведение при выполнении.

1.1. Именование файлов

Версионные миграции (Versioned)

Префикс V + версия + описание:
V<Версия>__<Описание>.sql


Пример:
-- V1__Create_users_table.sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL
);


Повторяемые миграции (Repeatable)

Префикс R + описание:
R__<Описание>.sql


Пример:
-- R__Update_user_view.sql
CREATE OR REPLACE VIEW user_view AS
SELECT id, username FROM users;


2. Java-миграции

Позволяют описывать миграции на Java для сложной логики, недоступной в SQL.

2.1. Реализация интерфейсов


JdbcMigration (устаревший):
public class V2__InsertTestData implements JdbcMigration {
@Override
public void migrate(Connection connection) throws Exception {
try (Statement stmt = connection.createStatement()) {
stmt.execute("INSERT INTO users (username) VALUES ('admin')");
}
}
}


JavaMigration (рекомендуемый):
public class V3__AddAdminUser implements JavaMigration {
@Override
public void migrate(Context context) throws Exception {
try (Statement stmt = context.getConnection().createStatement()) {
stmt.execute("INSERT INTO users (username) VALUES ('superuser')");
}
}
}


2.2. Правила

Классы должны находиться в classpath (обычно src/main/java/db/migration).
Имя класса соответствует имени файла SQL-миграции (например, V2__InsertTestData.java).

3. Правила версионирования

3.1. Семантическое версионирование

Рекомендуемый формат версии:
V<Мажор>.<Минор>.<Патч>__<Описание>.sql


Пример:
-- V1.2.3__Fix_email_constraint.sql
ALTER TABLE users ALTER COLUMN email SET NOT NULL;


Преимущества:
Понятная история изменений.
Совместимость с Semantic Versioning.


3.2. Откат изменений

Flyway не поддерживает автоматический откат. Альтернативы:

Новая миграция для отмены изменений:
-- V3__Drop_users_table.sql
DROP TABLE users;


Callbacks (SQL-хуки):
Скрипты beforeMigrate/afterMigrate для резервного копирования.

Важно: Не изменяйте уже примененные миграции — это нарушит целостность flyway_schema_history.

4. Примеры

4.1. SQL-миграции
-- V1__Initial_schema.sql
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100)
);

-- R__Update_view.sql
CREATE OR REPLACE VIEW active_users AS
SELECT * FROM users WHERE deleted_at IS NULL;


4.2. Java-миграция

public class V4__EncryptPasswords implements JavaMigration {
@Override
public void migrate(Context context) throws Exception {
try (PreparedStatement ps = context.getConnection()
.prepareStatement("UPDATE users SET password = encrypt(password)")) {
ps.executeUpdate();
}
}
}


#Java #middle #Flyway
Интеграция Flyway с инструментами

1. Maven: плагин flyway-maven-plugin
Настройка в pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>9.22.0</version>
<configuration>
<url>jdbc:postgresql://localhost:5432/mydb</url>
<user>postgres</user>
<password>password</password>
<locations>
<location>classpath:db/migration</location>
</locations>
</configuration>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>


Ключевые параметры:

url — JDBC-строка подключения.
locations — пути к папкам с миграциями (classpath: или filesystem:).
baselineVersion — версия для инициализации существующей БД (если не пустая).


Команды:
mvn flyway:migrate  # Применить миграции
mvn flyway:info # Показать статус
mvn flyway:clean # Очистить БД (удалить все объекты)


2. Gradle: плагин org.flywaydb.flyway
Настройка в build.gradle:
plugins {
id "org.flywaydb.flyway" version "9.22.0"
}

flyway {
url = 'jdbc:postgresql://localhost:5432/mydb'
user = 'postgres'
password = 'password'
locations = ['classpath:db/migration']
}

dependencies {
flywayRuntime 'org.postgresql:postgresql:42.6.0'
}


Команды:
gradle flywayMigrate  # Применить миграции
gradle flywayInfo # Показать статус


3. Интеграция с Spring Boot
Автоконфигурация через application.yml:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: password
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true # Игнорировать существующую БД
validate-on-migrate: false # Отключить валидацию (для dev)


Принцип работы:

При старте приложения Spring Boot автоматически:
Проверяет наличие таблицы flyway_schema_history.
Применяет невыполненные миграции из указанных в locations.
Если baseline-on-migrate: true,
Flyway инициализирует БД без ошибок, даже если она не пуста.

Важные свойства:
spring.flyway.clean-disabled — запрет на случайную очистку БД (по умолчанию true в prod).
spring.
flyway.table — кастомное имя для таблицы истории (по умолчанию flyway_schema_history).

4. Callbacks (SQL-хуки)

SQL-скрипты, выполняемые до/после основных операций Flyway (миграции, очистки и т.д.).

Поддерживаемые события:
beforeMigrate, afterMigrate
beforeClean, afterClean
beforeInfo, afterInfo


Пример использования:


Создайте файл db/migration/beforeMigrate.sql:
-- beforeMigrate.sql
CREATE TABLE IF NOT EXISTS _flyway_audit (
operation VARCHAR(20),
timestamp TIMESTAMP
);
INSERT INTO _flyway_audit VALUES ('migration_started', NOW());


Flyway выполнит этот скрипт перед применением миграций.

Правила:
Имена файлов должны соответствовать шаблону: <event>.sql (например, afterMigrate.sql).
Размещаются в папке locations (рядом с миграциями).


5. Мультимодульные проекты (Maven/Gradle)

Если миграции находятся в отдельном модуле:
Укажите путь к ресурсам через filesystem::
<!-- Maven -->
<location>filesystem:${project.basedir}/../migrations/src/main/resources/db/migration</location>


// Gradle
locations = ['filesystem:../migrations/src/main/resources/db/migration']


6. Пропуск миграций в тестах

В application-test.yml:
spring:
flyway:
enabled: false


7. Кастомные места хранения миграций

S3-хранилище (через Flyway Teams):
spring:
flyway:
locations: s3://my-bucket/db/migration


Классовый путь + файловая система:
locations: classpath:db/migration, filesystem:/opt/migrations


#Java #middle #Flyway
Best Practices и расширенные сценарии работы с Flyway

1. Организация миграций

1.1. Разделение миграций по окружениям

Проблема:
Разные БД для dev/test/prod могут требовать специфичных скриптов (например, тестовые данные только для dev).

Решение:
Структура папок:

db/
migration/
dev/
V1__Dev_only_data.sql
prod/
V1__Prod_indexes.sql
common/
V1__Base_schema.sql


Настройка application.yml для dev:
spring:
flyway:
locations: classpath:db/migration/common, classpath:db/migration/dev


1.2. Работа с существующей БД (baseline)

Проблема:
Flyway ожидает пустую БД или таблицу flyway_schema_history. Если БД уже используется, требуется инициализация.

Решение:
Включить baseline-on-migrate:

spring:
flyway:
baseline-on-migrate: true
baseline-version: 1.0 # Версия, с которой начнется контроль


Вручную через CLI:

flyway baseline -baselineVersion="1.0"


Важно:
После baseline миграции с версией ≤ baselineVersion игнорируются.


2. Тестирование миграций

2.1. Интеграция с Testcontainers + JUnit

Цель:
Проверить, что миграции применяются без ошибок в изолированной БД.

Пример теста (Java + JUnit 5):
import org.flywaydb.core.Flyway;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
public class FlywayMigrationTest {

@Container
private static final PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:15");

@Test
void testMigrations() {
Flyway flyway = Flyway.configure()
.dataSource(
postgres.getJdbcUrl(),
postgres.getUsername(),
postgres.getPassword()
)
.load();
flyway.migrate(); // Упадет, если есть ошибки
}
}


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



3. Работа в команде

3.1. Именование файлов

Правила:
Уникальность версий:
Используйте дату + порядковый номер: V20240315-1__Add_users_table.sql.

Описательные имена:
Плохо: V1__Changes.sql.
Хорошо: V20240315-2__Alter_users_add_email.sql.


3.2. Запрет изменения примененных скриптов

Проблема:
Изменение уже выполненного скрипта приводит к ошибке:

Validate failed: Migration checksum mismatch for V1__Create_table.sql


Решение:
Никогда не изменять содержимое V*-файлов после их применения.

Для исправлений:
Создать новую миграцию с корректировкой:
-- V20240315-3__Fix_users_table.sql
ALTER TABLE users ALTER COLUMN email SET NOT NULL;

Если критично, использовать flyway repair (пересчитывает контрольные суммы).

Исключение:
R__-миграции (повторяемые) можно изменять — они переприменяются при изменениях.


4. Расширенные сценарии

4.1. Миграции для нескольких схем БД

Настройка:
spring:
flyway:
schemas: public, audit
default-schema: public
В SQL-файлах укажите схему явно:

sql
-- V1__Create_audit_table.sql
CREATE TABLE audit.logs (
id SERIAL PRIMARY KEY,
message TEXT
);


4.2. Шаблонизация SQL

Проблема:
Разные SQL-синтаксисы для PostgreSQL/Oracle.

Решение (через Maven/Gradle):
Используйте placeholders в pom.xml:
<configuration>
<placeholders>
<table.prefix>${env}</table.prefix>
</placeholders>
</configuration>


В SQL:
CREATE TABLE ${table.prefix}_users (...);


4.3. Откаты (безопасная альтернатива)


Тактика:
Для деструктивных изменений (DROP, DELETE) создавать "обратные" миграции:
-- V5__Drop_users.sql
DROP TABLE users;

-- V6__Restore_users.sql (если нужно откатить)
CREATE TABLE users (...); -- Повторяем структуру из V1
INSERT INTO users (...) SELECT ... FROM backup_users;
Использовать резервные копии перед рискованными операциями.


#Java #middle #Flyway