Миграции базы данных: Flyway
Режим ddl-auto: update удобен в первый день, но опасен дальше: Hibernate не удаляет и не переименовывает столбцы, а на сервере вы не знаете, какой SQL он выполнит. Правильный путь — миграции: SQL-файлы с номерами версий, которые лежат в проекте рядом с кодом. Библиотека Flyway при запуске смотрит, какие из них уже применены, и выполняет новые по порядку.
Подключение
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway</artifactId>
</dependency>Для PostgreSQL добавьте ещё модуль org.flywaydb:flyway-database-postgresql — на start.spring.io он подключается сам, если выбрать Flyway и PostgreSQL вместе.
Первая миграция
Создайте папку src/main/resources/db/migration и файл в ней:
-- src/main/resources/db/migration/V1__create_tables.sql
create table users (
id bigint generated by default as identity primary key,
username varchar(255) not null unique
);
create table posts (
id bigint generated by default as identity primary key,
title varchar(120) not null,
body varchar(10000) not null,
created_at timestamp(6) with time zone not null,
author_id bigint not null references users (id)
);
create table comments (
id bigint generated by default as identity primary key,
text varchar(1000) not null,
created_at timestamp(6) with time zone not null,
post_id bigint not null references posts (id),
author_id bigint not null references users (id)
);Имя файла строится строго: V, номер версии, два подчёркивания, описание. Этот SQL подходит и для H2, и для PostgreSQL.
Hibernate только проверяет
Теперь таблицы создаёт Flyway, а Hibernate лишь сверяет их с сущностями:
# src/main/resources/application.yaml
spring:
jpa:
hibernate:
ddl-auto: validateУдалите папку data, чтобы начать с пустой базы, и запустите приложение:
INFO ... Database: jdbc:h2:file:./data/blog (H2 2.4)
INFO ... Creating Schema History table "PUBLIC"."flyway_schema_history" ...
INFO ... Current version of schema "PUBLIC": << Empty Schema >>
INFO ... Migrating schema "PUBLIC" to version "1 - create tables"
INFO ... Successfully applied 1 migration to schema "PUBLIC", now at version v1В таблице flyway_schema_history Flyway записывает, какие версии применены. При следующем запуске он увидит версию 1 и ничего выполнять не будет. Предупреждение о том, что версия H2 новее проверенной Flyway, на работу не влияет.
Новая миграция
Нужен новый столбец — пишем следующий файл, старые не трогаем:
-- src/main/resources/db/migration/V2__add_password_and_role.sql
alter table users add column password varchar(100) not null default '';
alter table users add column role varchar(20) not null default 'USER';Эта миграция понадобится в главе о безопасности. Flyway применит её при следующем запуске — и на вашем компьютере, и на сервере, одинаково.
Если сущность и таблица не совпадают
Добавьте в сущность поле, забыв про миграцию, — validate не даст запуститься:
Schema validation: missing column [subtitle] in table [posts]Это защита: лучше упасть при старте, чем получить ошибку SQL на первом же запросе.
Частая ошибка
Нельзя менять миграцию, которая уже применена. Flyway хранит контрольную сумму каждого файла и при запуске сверяет её:
Validate failed: Migrations have failed validation
Migration checksum mismatch for migration version 1
-> Applied to database : 2136568703
-> Resolved locally : -1628166330
Either revert the changes to the migration, or run repair to update the schema history.Верните файл как было и оформите изменение новой миграцией V2__.... На своём компьютере, пока данные не важны, можно просто удалить папку data — база создастся заново.