Liquibase有助于自动化数据库迁移,而Spring Boot使使用Liquibase更加容易。该指南提供了有关如何在Spring Boot应用程序中使用Liquibase的详细信息以及一些最佳实践。
本文随附 GitHub上 的工作代码示例。
数据库迁移工具可帮助我们跟踪,版本控制和自动执行数据库架构更改。它们帮助我们在不同环境中拥有一致的架构。
Liquibase简介
Liquibase不仅使用简单的旧SQL脚本,而且还使用不同的抽象的,与数据库无关的格式(包括XML,YAML和JSON)来促进数据库迁移。当我们使用非SQL格式进行数据库迁移时,Liquibase会为我们生成特定于数据库的SQL。它照顾不同数据库的数据类型和SQL语法的变化。它支持大多数流行的 关系数据库 。
Liquibase允许通过 Liquibase扩展 对其当前支持的数据库进行增强。这些扩展也可用于添加对其他数据库的支持。
让我们看一下Liquibase的核心概念:
Liquibase会创建两个表,databasechangelog 并databasechangeloglock在第一次在数据库中运行时创建。它使用该databasechangelog表来跟踪databasechangeloglockchangeSets 的执行状态,并防止Liquibase并发执行。有关更多详细信息,请参考 文档 。
Spring Boot的Liquibase
默认情况下,当我们将 Liquibase依赖 项添加到构建文件中时,Spring Boot会自动配置Liquibase 。
Spring Boot使用主数据库DataSource运行Liquibase.如果我们需要使用其他名称DataSource,可以将该bean标记为@LiquibaseDataSource。
另外,我们可以设置spring.liquibase.[url,user,password]属性,以便spring自己创建一个数据源,并使用它来自动配置Liquibase。
默认情况下,Spring Boot在应用程序启动时自动运行Liquibase数据库迁移。
在类路径中名为db/migration的文件夹中查找主变更日志文件db.changelog-master.yaml。如果要使用其他Liquibase变更日志格式或使用不同的文件命名约定,则可以将spring.liquibase.change-log应用程序属性配置为指向其他主变更日志文件。
例如,要用db/migration/my-master-change-log.json作主变更日志文件,我们在中设置以下属性application.yml:
spring: liquibase: changeLog: <font>"classpath:db/migration/my-master-change-log.json"</font><font> </font>
主变更日志可以 包括 其他变更日志,以便我们可以按逻辑步骤将变更拆分。
运行我们的第一个数据库迁移
设置完所有内容后,让我们创建我们的第一个数据库迁移。在本示例中,我们将创建数据库表user_details。
让我们创建一个具有名称的文件db.changelog-master.yaml并将其放置在中src/main/resources/db/changelog:
databaseChangeLog: - include: file: db/changelog/db.changelog-yaml-example.yaml
主文件只是一个包含集合的集合,这些集合指向具有实际更改的更改日志。
接下来,我们使用第一个实际的变更集创建变更日志,并将其放入文件中src/main/resources/db/changelog-yaml-example.yaml:
databaseChangeLog: - changeSet: id: create-table-user author: liquibase-demo-service preConditions: - onFail: MARK_RAN not: tableExists: tableName: user_details changes: - createTable: columns: - column: autoIncrement: <b>true</b> constraints: nullable: false primaryKey: <b>true</b> primaryKeyName: user_pkey name: id type: BIGINT - column: constraints: nullable: false name: username type: VARCHAR(250) - column: constraints: nullable: false name: first_name type: VARCHAR(250) - column: name: last_name type: VARCHAR(250) tableName: user_details
我们使用了changeType createTable,它抽象了表的创建。Liquibase将基于我们的应用程序使用的数据库将上述changeSet转换为适当的SQL。
在执行此更改之前,preCondition检查user_details表是否不存在。如果该表已经存在,则Liquibase会将changeSet标记为已成功运行而不实际运行。
现在,当我们运行Spring Boot应用程序时,Liquibase执行changeSet,该表将创建user_details表,user_pkey作为主键。
使用变更日志参数
当我们要为不同的环境使用不同的值替换占位符时,Changelog参数非常有用。我们可以使用application属性设置这些参数spring.liquibase.parameters,该属性采用键/值对的映射:
spring: profiles: docker liquibase: parameters: textColumnType: TEXT contexts: local --- spring: profiles: h2 liquibase: parameters: textColumnType: VARCHAR(250) contexts: local
我们设置Liquibase参数textColumnType来VARCHAR(250)时春启动的启动h2配置文件,并TEXT当它在启动docker配置文件(假定泊坞窗型材启动一个“真正”的数据库)。
现在,我们可以在变更日志中使用此参数:
databaseChangeLog: - changeSet: ... changes: - createTable: columns: ... - column: constraints: nullable: false name: username type: ${textColumnType}
现在,当Spring Boot应用程序在docker配置文件中运行时,它将TEXT用作列类型,并在h2配置文件中使用VARCHAR(250)。
使用Liquibase上下文
上下文可用于控制应运行哪些changeSet。让我们用它在test和local环境中添加测试数据:
<databaseChangeLog> <changeSet author=<font>"liquibase-docs"</font><font> id=</font><font>"loadUpdateData-example"</font><font> context=</font><font>"test or local"</font><font>> <loadUpdateData encoding=</font><font>"UTF-8"</font><font> file=</font><font>"db/data/users.csv"</font><font> onlyUpdate=</font><font>"false"</font><font> primaryKey=</font><font>"id"</font><font> quotchar=</font><font>"'"</font><font> separator=</font><font>","</font><font> tableName=</font><font>"user_details"</font><font>> </loadUpdateData> </changeSet> </databaseChangeLog> </font>
我们正在使用该表达式test or local,它可以在这些上下文中运行,但不适用于生产环境。
现在,我们需要使用属性将上下文传递给Liquibase spring.liquibase.contexts:
--- spring: profiles: docker liquibase: parameters: textColumnType: TEXT contexts: test
在Spring Boot中配置Liquibase
下面是Spring Boot提供的用于配置Liquibase行为的所有属性的列表。
在Spring Boot中启用Liquibase的日志记录
INFO为Liquibase 启用级别日志记录将有助于查看Liquibase在应用程序启动期间执行的changeSet。它还有助于识别应用程序尚未启动,因为它在启动过程中正在等待获取变更日志锁。
在其中添加以下应用程序属性application.yml以启用INFO日志:
logging: level: <font>"liquibase"</font><font> : info </font>
使用Liquibase的最佳实践
在Spring Boot应用程序启动期间自动运行Liquibase,可以轻松地将应用程序代码更改和数据库更改一起提供。但是,在向具有大量数据的现有数据库表添加索引的情况下,应用程序可能需要更长的时间才能启动。一种选择是预发布数据库迁移(在需要它的代码之前释放数据库更改)并 异步运行它们 。
其他运行Liquibase的方法
Liquibase除了支持Spring Boot集成外,还支持一系列其他选项来运行数据库迁移:
Liquibase有一个 Java API ,我们可以在任何基于Java的应用程序中使用它来执行数据库迁移。