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

Используйте Liquibase для безопасного развития схемы вашей базы данных

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

1. Обзор

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

Сначала мы рассмотрим общее Java-приложение, а также подробно рассмотрим некоторые интересные варианты, доступные для Spring и Hibernate.

Вкратце, ядром использования Liquibase является файл changeLog , XML-файл, в котором отслеживаются все изменения, которые необходимо выполнить для обновления БД.

Давайте начнем с зависимости Maven, которую нам нужно добавить в наш pom.xml :

<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.4.1</version>
</dependency>

Мы также можем проверить, есть ли более новая версия liquibase-core здесь .

2. Журнал изменений базы данных

Теперь давайте взглянем на простой файл журнала изменений .

Этот только добавляет столбец « адрес » в таблицу « пользователи »:

<databaseChangeLog 
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">

<changeSet author="John" id="someUniqueId">
<addColumn tableName="users">
<column name="address" type="varchar(255)" />
</addColumn>
</changeSet>

</databaseChangeLog>

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

Давайте теперь посмотрим, как связать это с нашим приложением и убедиться, что оно запускается при запуске приложения.

3. Запустите Liquibase с помощью Spring Bean

Наш первый вариант запуска изменений при запуске приложения — через Spring bean.

Конечно, есть много других способов, но это хороший и простой способ, если мы имеем дело с приложением Spring:

@Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setChangeLog("classpath:liquibase-changeLog.xml");
liquibase.setDataSource(dataSource());
return liquibase;
}

Обратите внимание, как мы указываем на действительный файл журнала изменений , который должен существовать в пути к классам.

4. Используйте Liquibase с Spring Boot

Если мы используем Spring Boot , нет необходимости определять bean -компонент для Liquibase, но нам все равно нужно убедиться, что мы добавили зависимость от liquibase-core.

Затем все, что нам нужно, это поместить наш журнал изменений в db/changelog/db.changelog-master.yaml , и миграция Liquibase будет выполняться автоматически при запуске.

Мы можем изменить файл журнала изменений по умолчанию, используя свойство liquibase.change-log :

liquibase.change-log=classpath:liquibase-changeLog.xml

5. Отключить Liquibase в Spring Boot

Иногда нам может потребоваться отключить выполнение миграции Liquibase при запуске.

Самый простой вариант, который у нас есть, — использовать свойство spring.liquibase.enabled . Таким образом, вся оставшаяся конфигурация Liquibase останется нетронутой.

Вот пример для Spring Boot 2:

spring.liquibase.enabled=false

Для Spring Boot 1.x нам нужно использовать свойство liquibase.enabled :

liquibase.enabled=false

6. Создайте журнал изменений с помощью плагина Maven.

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

6.1. Конфигурация плагина

Вот изменения в нашем pom.xml :

<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
</dependency>
...
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
</plugins>

6.2. Создание журнала изменений из существующей базы данных

Мы можем использовать плагин для создания журнала изменений из существующей базы данных:

mvn liquibase:generateChangeLog

Вот свойства ликвибазы :

url=jdbc:mysql://localhost:3306/oauth_reddit
username=tutorialuser
password=tutorialmy5ql
driver=com.mysql.jdbc.Driver
outputChangeLogFile=src/main/resources/liquibase-outputChangeLog.xml

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

Вот как это будет выглядеть:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog ...>

<changeSet author="John (generated)" id="1439225004329-1">
<createTable tableName="APP_USER">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints primaryKey="true"/>
</column>
<column name="accessToken" type="VARCHAR(255)"/>
<column name="needCaptcha" type="BIT(1)">
<constraints nullable="false"/>
</column>
<column name="password" type="VARCHAR(255)"/>
<column name="refreshToken" type="VARCHAR(255)"/>
<column name="tokenExpiration" type="datetime"/>
<column name="username" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="preference_id" type="BIGINT"/>
<column name="address" type="VARCHAR(255)"/>
</createTable>
</changeSet>
...
</databaseChangeLog>

6.3. Создайте журнал изменений из различий между двумя базами данных

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

mvn liquibase:diff

Вот свойства:

changeLogFile=src/main/resources/liquibase-changeLog.xml
url=jdbc:mysql://localhost:3306/oauth_reddit
username=tutorialuser
password=tutorialmy5ql
driver=com.mysql.jdbc.Driver
referenceUrl=jdbc:h2:mem:oauth_reddit
diffChangeLogFile=src/main/resources/liquibase-diff-changeLog.xml
referenceDriver=org.h2.Driver
referenceUsername=sa
referencePassword=

А вот фрагмент сгенерированного журнала изменений :

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog ...>
<changeSet author="John" id="1439227853089-1">
<dropColumn columnName="address" tableName="APP_USER"/>
</changeSet>
</databaseChangeLog>

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

7. Используйте плагин Liquibase Hibernate

В случае, если наше приложение использует Hibernate, мы рассмотрим очень полезный способ создания журнала изменений , которым является плагин liquibase - hibernate . ``

7.1. Конфигурация плагина

Во-первых, давайте настроим новый плагин и используем правильные зависимости:

<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
<dependencies>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate4</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.3.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>

7.2. Создание журнала изменений из различий между базой данных и сущностями персистентности

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

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

Вот свойства ликвибазы :

changeLogFile=classpath:liquibase-changeLog.xml
url=jdbc:mysql://localhost:3306/oauth_reddit
username=tutorialuser
password=tutorialmy5ql
driver=com.mysql.jdbc.Driver
referenceUrl=hibernate:spring:org.foreach.persistence.model
?dialect=org.hibernate.dialect.MySQLDialect
diffChangeLogFile=src/main/resources/liquibase-diff-changeLog.xml

Обратите внимание, что referenceUrl использует сканирование пакетов, поэтому параметр диалекта является обязательным.

8. Создайте журнал изменений в IntelliJ IDEA с помощью подключаемого модуля JPA Buddy.

Если мы используем не-Hibernate ORM (например, EclipseLink или OpenJPA) или не хотим добавлять дополнительные зависимости, такие как плагин liquibase-hibernate , мы можем использовать JPA Buddy . Этот плагин IntelliJ IDEA интегрирует полезные функции Liquibase в IDE.

Чтобы сгенерировать дифференциальный журнал изменений , мы просто устанавливаем плагин, а затем вызываем действие из панели структуры JPA. Мы выбираем, какой источник мы хотим сравнить (база данных, сущности JPA или моментальный снимок Liquibase) с какой целью (база данных или моментальный снимок Liquibase).

JPA Buddy сгенерирует журнал изменений , как показано на анимации ниже :

./c44109c2c3f5d62283b7e1fa9d51b99b.gif

Еще одним преимуществом JPA Buddy по сравнению с подключаемым модулем liquibase-hibernate является возможность переопределения сопоставлений по умолчанию между типами Java и баз данных. Кроме того, он корректно работает с пользовательскими типами Hibernate и конвертерами JPA.

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

В этой статье мы проиллюстрировали несколько способов использования Liquibase и нашли безопасный и зрелый способ развития и рефакторинга схемы БД приложения Java.

Реализация всех этих примеров и фрагментов кода доступна на GitHub .