Spring boot 将liquibase添加到现有spring引导项目的正确方法
我有一个现有的spring boot项目和一个数据库。现在,我想添加liquibase来处理进一步的数据库迁移。执行此操作的正确步骤是什么 我随后添加了liquibase并生成了changelog。我发现的大多数文章都谈到在项目中从头开始使用liquibase,或者没有太详细地介绍实现。到目前为止,我已经做了以下工作: 在pom.xml中添加了依赖项和插件Spring boot 将liquibase添加到现有spring引导项目的正确方法,spring-boot,database-migration,liquibase,Spring Boot,Database Migration,Liquibase,我有一个现有的spring boot项目和一个数据库。现在,我想添加liquibase来处理进一步的数据库迁移。执行此操作的正确步骤是什么 我随后添加了liquibase并生成了changelog。我发现的大多数文章都谈到在项目中从头开始使用liquibase,或者没有太详细地介绍实现。到目前为止,我已经做了以下工作: 在pom.xml中添加了依赖项和插件 <dependencies> //..other dependencies <dependency>
<dependencies>
//..other dependencies
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
</plugins>
</build>
更新了src/main/resources下的application.properties文件以处理变更日志
#Hibernate
spring.datasource.url=jdbc:mysql://localhost:3306/demodb
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
#Jpa
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
#Liquibase
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml
在src/main/resources/db/changelog下创建了db.changelog master.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.liquibase.org/xml/ns/dbchangelog/1.9
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
</databaseChangeLog>
然后在liquibase.properties
added中同步当前已执行的变更日志:
changeLogFile=src/main/resources/db/changelog/changes/demodb-changelog.xml
然后从终端运行:
mvn liquibase:changelogSync
现在,DATABASECHANGELOG
表中有已执行的变更日志条目
接下来在db.changelog master.xml
文件中,添加了生成的文件:
<include file="db/changelog/changes/demodb-changelog.xml"/>
因此,这是在尝试再次运行changelog文件。如何配置为仅运行那些尚未运行的变更集?我以为DATABASECHANGELOG
的功能是处理已执行的变更集,但我猜我错了
我可以在没有db.changelog master.xml
中的include
标记的情况下运行该应用程序,但我想这里需要列出所有的changelog文件,因为如果我要在另一台机器上运行该应用程序,从头开始创建整个数据库,我需要所有的changelog文件
那么如何将liquibase配置为只运行尚未执行的变更日志呢?MySQL将在表中维护liquibase的日志 Liquibase使用DATABASECHANGELOG表跟踪已运行的变更集 无论何时运行变更日志,都会为每个变更日志添加一行表,根据ID,我们可以知道运行了哪些变更日志 有一些标志,如
runAlways
,runOnChange
,它们将帮助我们执行/不执行
你可以参考:
For understanding flags:
这里的问题是存储在
数据库更改日志
表中的文件名
字段
Liquibase不仅通过id
或id
和author
来确定变更集的身份,而是基于所有三个字段的值来确定变更集的身份:
id
,author
,filename
运行mvn liquibase:update
或mvn liquibase:changelogSync
时,变更日志的文件名
为src/main/resources/db/changelog/changes/demodab changelog.xml
。这是liquibase存储到每个表行的DATABASECHANGELOG.FILENAME
字段中的值
但是,当您启动spring boot应用程序时,变更日志的文件名是classpath:db/changelog/db.changelog master.xml
,其中包含的变更日志的文件名是db/changelog/changes/demodab changelog.xml
然后,Liquibase检查已经应用了哪些变更集
它检查DATABASECHANGELOG
表中每个变更集的id
、author
和filename
,以及db/changelog/changes/demodab changelog.xml
文件中的每个变更集,发现没有匹配的内容,因为filename
字段不同。在DB中,它的值是src/main/resources/DB/changelog/changes/demodab changelog.xml
src/main/resources/db/changelog/changes/demodb-changelog.xml != db/changelog/changes/demodb-changelog.xml
因此,Liquibase认为这些是不同的变更集,并尝试应用它们。它失败,因为表已经存在。但是,如果您将变更集更改为可以多次应用的内容,您将看到Liqibase为数据库变更日志
表中的行创建了一个新的变更集,具有相同的id
,相同的作者
,但不同的文件名
老实说,我不知道如何解决这个问题。这看起来像是Spring Boot中Liquibase如何工作的一个基本问题。当在spring启动应用程序启动时读取changelog文件时,它们必须位于类路径中,尤其是在使用默认fat jar的情况下。但当您以maven插件的形式运行Liquibase时,它们通常位于本地文件系统上(这不是真的,请参阅我的“更新2”)
可能存在一些解决方法,请将其添加到评论中,我将更新答案
更新
我发现的一个解决方法是使用标签的logicalFilePath
属性
用于在创建更改集的唯一标识符时替代文件名和路径。移动或重命名更改日志时需要
如果您在所有变更日志/变更集中仔细地设置它,它应该可以工作
db/changelog/changes/demodab changelog.xml
文件的示例:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd"
logicalFilePath="db/changelog/changes/demodb-changelog.xml">
</databaseChangeLog>
然后,当你跑的时候
mvn process-resources liquibase:changelogSync
Liquibase将在DATABASECHANGELOG
表中创建记录,其中FILENAME
字段等于db/changelog/changes/demodab changelog.xml
,这等于spring boot在启动时运行迁移时使用的文件名(classpath:
前缀在比较文件名时由Liquibase自动去除). 最后,这使Liquibase了解到,这些是相同的变更集集集,并且它们已经应用。在生成变更日志时,是否可以对所有变更集设置runAlways=“false”或runOnChange=“true”?还是应该手动执行此操作?runOnChange为true。有时,您必须根据情况删除表中的行。您是否尝试将生成的文件包含在changelog master中,然后运行changeLogSync?您在Update 2中的解决方案有效,这就是我正在玩的测试项目中的解决方案。然而,有一个有趣的怪癖。只是喝了酒
For understanding DATABASECHANGELOG Table:
src/main/resources/db/changelog/changes/demodb-changelog.xml != db/changelog/changes/demodb-changelog.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd"
logicalFilePath="db/changelog/changes/demodb-changelog.xml">
</databaseChangeLog>
changeLogFile=db/changelog/changes/demodb-changelog.xml
mvn process-resources liquibase:changelogSync