Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Миграции базы данных: 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 — база создастся заново.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.