Простая интеграция Spring Boot с Liquibase

Spring Boot
Простая интеграция Spring Boot с Liquibase

Liquibase— это инструмент рефакторинга базы данных с открытым исходным кодом для отслеживания, управления и применения изменений базы данных. Он сохраняет все изменения базы данных (как структуры, так и данных) вchangelogфайл, он удобен для контроля версий, и его цель — предоставить решение, не зависящее от типа базы данных, путем выполнения файлов типа схемы для достижения миграции.

Ликвибаза Особенности

Liquibase имеет следующие особенности:

  • Поддержка практически всех основных баз данных, таких как MySQL, PostgreSQL, Oracle, Sql Server, DB2 и т. д.;
  • Поддержка совместного обслуживания нескольких разработчиков;
  • Файл журнала поддерживает несколько форматов, таких как XML, YAML, JSON, SQL и т. д.;
  • Поддержка контекстно-зависимой логики
  • Создание документации по изменению базы данных
  • Поддерживает несколько режимов запуска, таких как командная строка, интеграция Spring, плагин Maven, плагин Gradle и т. д.

Для получения более подробной информации см.Официальная документация Liquibase

Spring Boot интегрирует Liquibase

добавить зависимости

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

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

Настроить файл приложения

Настройте файл application.properties или application.yml в пути к классам,

# 启用liquibase
liquibase.enabled=true
# 存储变化的文件(changelog)位置
liquibase.change-log=classpath:sample_change.sql
# 检查存储变化的文件是否存在
liquibase.check-change-log-location=true
# 分环境执行,若在 changelog 文件中设置了对应 context 属性,则只会执行与 dev 对应值的 changeset
liquibase.contexts=dev
# 执行前首先删除数据库,默认 false。若设置为 true,则执行变更前,会先删除目标数据库,请谨慎
liquibase.dropFirst=false
# 执行更新时将回滚 SQL 写入的文件路径
liquibase.rollback-file=
# 如果使用工程已配置的 datasource 数据源,则以下三个数据库连接参数可不配置
## 访问数据库的连接地址
liquibase.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
# 访问数据库的用户名
liquibase.user=test
# 访问数据库的密码
liquibase.password=test

Примечание. При использовании настроенного проектаdatasourceисточник данных, затемliquibase.url、liquibase.userиliquibase.passwordЭти три параметра нельзя настроить, а целевым источником данных является настроенный источник данных проекта. Поскольку Spring автоматически получит доступные источники данных для liquibase, подробности см. в этом классе:org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.

Напишите файл журнала изменений, в котором хранятся изменения

В настоящее время Liquibase поддерживает файлы журнала изменений в четырех форматах: XML, YAML, JSON и SQL. Для удобства и наглядности файл журнала изменений написан в формате на основе SQL ниже: sample_change.sql

--liquibase formatted sql

--changeset zhouyi:1
-- 创建用户表
CREATE TABLE `user` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `age` int(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--rollback drop table user;

--changeset zhouyi:2
insert into user(id, name, age) values(1,'张三',29);
insert into user(id, name, age) values(2,'李四',20);

После запуска приложения Spring Boot вы можете увидеть вывод из журнала:

2019-03-27 13:13:16.439 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - DELETE FROM test.DATABASECHANGELOGLOCK
2019-03-27 13:13:16.442 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - INSERT INTO test.DATABASECHANGELOGLOCK (ID, `LOCKED`) VALUES (1, 0)
2019-03-27 13:13:16.506 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT `LOCKED` FROM test.DATABASECHANGELOGLOCK WHERE ID=1
2019-03-27 13:13:16.586 [main] [] INFO  liquibase.lockservice.StandardLockService.info:42 - Successfully acquired change log lock
2019-03-27 13:13:16.697 [main] [] INFO  liquibase.changelog.StandardChangeLogHistoryService.info:42 - Creating database history table with name: test.DATABASECHANGELOG
2019-03-27 13:13:16.700 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - CREATE TABLE test.DATABASECHANGELOG (ID VARCHAR(255) NOT NULL, AUTHOR VARCHAR(255) NOT NULL, FILENAME VARCHAR(255) NOT NULL, DATEEXECUTED datetime NOT NULL, ORDEREXECUTED INT NOT NULL, EXECTYPE VARCHAR(10) NOT NULL, MD5SUM VARCHAR(35) NULL, `DESCRIPTION` VARCHAR(255) NULL, COMMENTS VARCHAR(255) NULL, TAG VARCHAR(255) NULL, LIQUIBASE VARCHAR(20) NULL, CONTEXTS VARCHAR(255) NULL, LABELS VARCHAR(255) NULL, DEPLOYMENT_ID VARCHAR(10) NULL)
2019-03-27 13:13:17.570 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT COUNT(*) FROM test.DATABASECHANGELOG
2019-03-27 13:13:17.575 [main] [] INFO  liquibase.changelog.StandardChangeLogHistoryService.info:42 - Reading from test.DATABASECHANGELOG
2019-03-27 13:13:17.579 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT * FROM test.DATABASECHANGELOG ORDER BY DATEEXECUTED ASC, ORDEREXECUTED ASC
2019-03-27 13:13:17.585 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT COUNT(*) FROM test.DATABASECHANGELOGLOCK
2019-03-27 13:13:17.678 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - CREATE TABLE `user` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `age` int(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2019-03-27 13:13:17.935 [main] [] INFO  liquibase.changelog.ChangeSet.info:42 - Custom SQL executed
2019-03-27 13:13:17.937 [main] [] INFO  liquibase.changelog.ChangeSet.info:42 - ChangeSet classpath:sample_change.sql::1::zhouyi ran successfully in 297ms
2019-03-27 13:13:17.938 [main] [] INFO  liquibase.executor.jvm.JdbcExecutor.info:42 - SELECT MAX(ORDEREXECUTED) FROM test.DATABASECHANGELOG

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

数据库变更

вDATABASECHANGELOGиDATABASECHANGELOGLOCKТаблица автоматически генерируется Liquibase, аuserТаблица предназначена для выполнения того, что мы написалиchangesetПосле создания набора изменений и выполнения второго набора изменений вставляются две части данных.

Файл журнала изменений в формате SQL

в формате SQLchangelogФайл использует комментарии SQL в качестве метаданных, чтобы гарантировать, что этот файл распознается Liquibase какchangelogфайл, файл SQL должен начинаться со следующего комментария:

--liquibase formatted sql

набор изменений

в формате SQLchangelogСледующие комментарии необходимо добавить перед измененным SQL в файле, который выражается какchangesetНабор изменений:

--changeset author:id attribute1:value1 attribute2:value2 [...]

в предыдущемsample_change.sqlВ файле написано дваchangeset(набор изменений),

набор измененийchangesetчерезauthor + idспособ гарантировать уникальность, как указано вышеzhouyi:1иzhouyi:2Две таблицы обновлены.

Набор изменений предоставляет следующие свойства:

Атрибуты инструкция
stripComments Установите значение true, чтобы удалить все комментарии в SQL перед выполнением, в противном случае — значение false. Если не установлено, значение по умолчанию равно true
splitStatements
endDelimiter Разделитель применяется к концу оператора. По умолчанию ";", также можно установить ""
runAlways Выполнять наборы изменений при каждом запуске, даже если они были запущены до
runOnChange Просматривайте изменения в первый раз и выполняйте изменения каждый раз, когда изменяется набор изменений.
context Выполняет изменения, если определенный контекст передается во время выполнения. Любая строка может использоваться в качестве имени контекста и нечувствительна к регистру.
logicalFilePath Используется для переопределения имен файлов и путей при создании уникального идентификатора набора изменений. Требуется при перемещении или переименовании журналов изменений.
labels Метки — это распространенный метод классификации наборов изменений, наборов похожих контекстов, но работающих противоположным образом. Если вместо определения набора контекстов во время выполнения, а затем определения выражения соответствия в наборе изменений, определите набор тегов в контексте и определите выражение соответствия во время выполнения.
runInTransaction Должен ли набор изменений выполняться как одна транзакция (если возможно), значение по умолчанию — true. Обратите внимание, что если для этого свойства задано значение false и возникает ошибка при выполнении раздела набора изменений, содержащего несколько операторов, база данных liquibasedatabasechangeloglockТаблица будет в недопустимом состоянии
failOnError Должна ли миграция возвращать ошибку, если при выполнении набора изменений возникает ошибка
dbms Тип базы данных, используемой для этого набора изменений. Когда шаг миграции выполняется, он проверяет тип базы данных на соответствие этому свойству, например: oracle, mysql
logicalFilePath в базе данныхdatabasechangeloglockЗадайте путь к логическому файлу в , а не к физическому местоположению файла sql, в котором выполняется liquibase.

предварительное условие

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

--preconditions onFail:HALT onError:HALT
--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM my_table

операция отката

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

--rollback SQL STATEMENT

Например, первый набор изменений в файле журнала изменений, написанном ранее:

--changeset zhouyi:1
-- 创建用户表
CREATE TABLE `user` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `age` int(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--rollback drop table user;

Значение SQL первого изменения заключается в создании новогоuserтаблица, откат SQL означает удаление вновь созданнойuserповерхность.

Лучшие практики Liquibase

Ниже приведены некоторые рекомендации, которые вы можете применить к своим проектам.

Набор изменений устанавливает только одно изменение

По возможности избегайте внесения нескольких изменений в набор изменений, чтобы избежать автоматической фиксации операторов SQL, которые могут оставить базу данных в непредвиденном состоянии. как--changeset zhouyi:1Изменить набор, только создать новыйuserТаблица, набор изменений не будет изменен позже, если вам нужно изменить, вы можете добавить набор изменений.

ID набора изменений

Выберите метод, который работает для вас. Некоторые люди используют серийные номера, которые начинаются с 1 и являются уникальными в журнале изменений, другие выбирают описательное имя (например:new-address-table)

Всегда рассчитывайте на откат

Попробуйте написать наборы изменений таким образом, чтобы их можно было откатить, например.--changeset zhouyi:1Создать новый набор измененийuserтаблица, за которой следует откат SQL,--rollback drop table user;

Добавить комментарии к наборам изменений

Попробуйте добавить комментарий к каждой записи набора изменений, например.-- 创建用户表

Процесс использования разработчика

  • Используя вашу любимую IDE или редактор, создайте новый локальный набор изменений с изменениями;
  • Запустите Liquibase, чтобы выполнить новый набор изменений (это проверит код SQL);
  • Внесите соответствующие изменения в код приложения (например, Java-код);
  • Тесты проверяют новый код приложения и изменения в базе данных;
  • Зафиксируйте наборы изменений и код приложения.