Статьи

Миграция схемы с помощью Hibernate и FlywayDB

В этом руководстве объясняются преимущества использования инструмента автоматической миграции схем, такого как FlywayDB, а также ограничения утилиты создания схем Hibernate ( hbm2ddl ). В статье предполагается, что Hibernate почти не знает, и ее могут прочитать как начинающие, так и старшие разработчики.

Вступление

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

Шаблон объектно-реляционного отображения (ORM) направлен на решение этой проблемы, и Hibernate ORM , несомненно, является одной из наиболее успешных реализаций этого шаблона. Однако Hibernate — это нечто большее, чем инфраструктура ORM, которая соответствует спецификации Java Persistence API .

Hibernate — это структура доступа к данным, реализующая множество шаблонов, которые были популяризированы Мартином Фаулером в его книге « Шаблоны архитектуры корпоративных приложений» . Например, помимо типичной функции объектно-реляционного отображения, Hibernate также реализует следующие шаблоны доступа к данным:

Модель данных Двойственность

Хотя инструмент ORM позволяет нам преобразовывать изменения состояния графов объектов в операторы SQL, мы по-прежнему управляем двумя различными моделями данных. С одной стороны, схема базы данных определяет правила хранения данных, тогда как на стороне приложения модель домена является зеркалом объектного графа базовой схемы базы данных.

Итак, кто отвечает за представление модели? Это база данных или модель домена?

Схема владения

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

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

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

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

Схема-миграция

Схема миграции

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

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

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

В Java есть два варианта автоматической миграции схемы: Liquibase и FlywayDB . В этой статье я покажу вам, как легко можно интегрировать FlywayDB в корпоративное приложение Spring и Hibernate.

Во-первых, сценарии миграции схемы должны находиться в папке src/main/resources :

 resources flyway db postgresql migration V1_0__initial_script.sql V1_1__post_details.sql V1_2__post_comment.sql V1_3__post_tag.sql 

Учитывая, что у нас есть приложение Spring Framework, которое использует Hibernate для сохранения, для того, чтобы использовать FlywayDB, нам просто нужно настроить
org.flywaydb.core.Flyway Spring bean:

 @Bean(initMethod = "migrate") public Flyway flyway() { Flyway flyway = new Flyway(); flyway.setDataSource(actualDataSource()); flyway.setBaselineOnMigrate(true); flyway.setLocations( String.format( "classpath:/flyway/db/%1$s/migration", databaseType() ) ); return flyway; } к @Bean(initMethod = "migrate") public Flyway flyway() { Flyway flyway = new Flyway(); flyway.setDataSource(actualDataSource()); flyway.setBaselineOnMigrate(true); flyway.setLocations( String.format( "classpath:/flyway/db/%1$s/migration", databaseType() ) ); return flyway; } 

Еще одна вещь, которую следует учитывать, заключается в том, что LocalContainerEntityManagerFactoryBean , который отвечает за создание экземпляра Java EntityManagerFactory , должен быть инициализирован после компонента Flyway чтобы эти миграции выполнялись до начальной загрузки Hibernate.

 @Bean // depends on flyway bean, so that database initialization // runs before Hibernate gets bootstrapped @DependsOn("flyway") public LocalContainerEntityManagerFactoryBean entityManagerFactory() { // the usual initialization } 

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

 CREATE TABLE users (id BIGINT NOT NULL, name VARCHAR(255), PRIMARY KEY (id)); 

Нам просто нужно добавить его в папку ресурсов Flyway:

 resources flyway db postgresql migration V1_0__initial_script.sql V1_1__post_details.sql V1_2__post_comment.sql V1_3__post_tag.sql V1_4__users.sql 

И когда приложение запустится, Flyway собирается применить его автоматически:

 INFO : DbValidate - Validated 5 migrations (execution time 00:00.025s) DEBUG : DbSchemas - Schema "public" already exists. Skipping schema creation. DEBUG : Table - Locking table "public"."schema_version"... DEBUG : Table - Lock acquired for table "public"."schema_version" INFO : DbMigrate - Current version of schema "public": 1.3 INFO : DbMigrate - Migrating schema "public" to version 1.4 - users DEBUG : SqlScript - Found statement at line 1: create table users (id bigint not null, name varchar(255), primary key (id)) DEBUG : SqlScript - Executing SQL: create table users (id bigint not null, name varchar(255), primary key (id)) DEBUG : DbMigrate - Successfully completed and committed migration of schema "public" to version 1.4 DEBUG : MetaDataTableImpl - MetaData table "public"."schema_version" successfully updated to reflect changes DEBUG : Table - Locking table "public"."schema_version"... DEBUG : Table - Lock acquired for table "public"."schema_version" INFO : DbMigrate - Successfully applied 1 migration to schema "public" (execution time 00:00.091s). 

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

версия описание скрипт installed_on время исполнения успех
1,0 начальный сценарий V1_0__initial_script.sql 2016-08-05 07: 50: 22.418753 126 T
1,1 опубликовать детали V1_1__post_details.sql 2016-08-05 07: 50: 22.729402 164 T
1.2 Оставьте комментарий V1_2__post_comment.sql 2016-08-05 07: 50: 22.92953 97 T
1,3 пост тег V1_3__post_tag.sql 2016-08-05 07: 50: 23.038776 8 T
1.4 пользователи V1_4__users.sql 2016-08-05 07: 51: 35.315481 43 T

Вывод

Несмотря на то, что инструмент генерации схемы, предлагаемый Hibernate, полезен для тестирования или даже для создания первого начального сценария, в долгосрочной перспективе гораздо более гибко использовать инструмент автоматической миграции схемы, такой как FlywayDB. Таким образом, мы можем использовать все функции, предлагаемые специфичным для базы данных синтаксисом DDL, с минимальным количеством настроек.

Если вам понравилась эта статья, вам также может быть интересно прочитать мою книгу .