如何在 Spring Boot 中配置 Maven Liquibase 插件?
How can I configure Maven Liquibase plugin in Spring Boot?
我正在学习 Liquibase 和 Spring Boot,所以我用 Spring Initializr.
创建了一个简单的项目
在我添加的 POM.xml 文件中:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/application.properties</propertyFile>
</configuration>
</plugin>
我已将 application.properties 指定为 属性 文件,因此我的应用程序的所有配置都可以在一个文件中进行。
当我 运行 来自 IntelliJ 的任何 liquibase-maven-plugin 任务时,我得到不同的错误,这是一个示例 运行 执行 changeLogSync 任务:
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.4.1:changelogSync (default-cli) on project simpleTest: The changeLogFile must be specified
如果我在 application.properties 中添加正确的键,我就能让它工作。
例如,我发现 liquibase-maven-plugin 不会读取 spring.datasource.url 属性 但它只会读取 url 属性.
出于这个原因,我的 application.properties 必须是类似的东西:
environment = JUnit
spring.datasource.url = jdbc:h2:file:./target/test
spring.datasource.driver-class-name = org.h2.Driver
spring.datasource.username = sa
spring.datasource.password = sa
spring.liquibase.change-log = classpath:/db/changelog/db.changelog-master.yaml
spring.h2.console.enabled = true
spring.h2.console.path = /h2-console
# Keys needed for liquibase maven plugin
url = jdbc:h2:file:./target/test
username = sa
password = sa
如果我遵循这种模式,我最终会得到几个名称略有不同但在我的 application.properties 中具有相同值的键,这个解决方案显然非常丑陋且效率低下。
在 Spring 引导中配置和使用 Liquibase Maven 插件的有效且可维护的方法是什么?
在收到 Amith Kumar 的回答后进行编辑:
environment=JUnit
spring.datasource.url=jdbc:h2:file:./target/glossary-test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.yaml
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
url=${spring.datasource.url}
changeLogFile=${spring.liquibase.change-log}
username=${spring.datasource.username}
password=${spring.datasource.password}
编辑后出错:
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.4.1:dropAll (default-cli) on project test: Error setting up or running Liquibase: liquibase.exception.DatabaseException: java.lang.RuntimeException: Cannot find database driver: Driver class was not specified and could not be determined from the url (${spring.datasource.url}) -> [Help 1]
在很多项目中很常见。
当您使用多个 plug-ins/library 时,每个都期望环境配置中的某些属性,其中键名以其本机命名法定义。
这个问题没有标准化。
为了避免为多个属性提供相同的值,容易出错,建议您使用引用。
# Keys needed for liquibase maven plugin
url=${spring.datasource.url}
更新
我注意到当 运行 liquibase maven 插件当然在 spring 上下文之外运行时,您遇到了异常。我之前提供的解决方案适用于 spring 上下文,即当您启动应用程序时。
对于给定的场景,使用 maven filter resource files 特性。所以你的命令会变成
mvn liquibase:generateChangeLog resources:resources
您的设置如下所示:
src/main/filters/filter.properties
db.url=jdbc:h2:file:./target/glossary-test
db.username=sa
db.password=sa
db.driver=org.h2.Driver
db.lb.changeLogFile=classpath:/db/changelog/db.changelog-master.yaml
application.properties
spring.datasource.url=@db.url@
spring.datasource.username=@db.username@
spring.datasource.password=@db.password@
spring.datasource.driver-class-name=@db.driver@
url=@db.url@
username=@db.username@
password=@db.password@
driver=@db.driver@
changeLogFile=@db.lb.changeLogFile@
pom.xml
<build>
......
<plugins
......
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<propertyFile>target/classes/application.properties</propertyFile>
</configuration>
</plugin>
</plugins>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
请参阅我的 github project 以获得完整的工作解决方案。查看 filter.properties
文件,其中定义了通用属性,然后在 application.properties
文件中引用了相同的属性。
NOTE: Since this is a spring project, you can't use ${propertyName}
for maven filter file as its reserved property placeholder syntax for spring, but then use @propertyName@
. For non-spring project ${propertyName}
will work out of the box.
application.properties
设置非常快,可以启动 运行 应用程序,但在灵活性方面不是最佳解决方案
我的建议是使用 @Configuration
配置数据源,例如 here
然后配置上面定义的liquibase传递数据源如下
@Configuration
public class LiquibaseConfigurer {
@Autowired
@Qualifier("primaryDataSource")
private DataSource oltpDataSource;
@Bean
@DependsOn
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setChangeLog("classpath:liquibase/liquibase-changelog.xml");
liquibase.setDataSource(oltpDataSource);
return liquibase;
}
}
在这种情况下,您只需要 liquibase-core
如下依赖关系
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
一个更简单的替代方法是在没有 maven 插件的应用程序外部配置 liquibase。
下载库,或使用一些包管理器安装它,然后启动包含所有设置的命令行
liquibase --driver=org.h2.Driver \
--classpath=/path/to/h2/driver.jar \
--changeLogFile=/db/changelog/db.changelog-master.yaml \
--url="jdbc:h2:file:./target/glossary-test" \
--username=sa \
--password=sa \
--logLevel=debug \
migrate
无论如何,你现在遇到的问题是因为你写了这个:
url=${spring.datasource.url}
我不知道你在哪里找到这个语法,但尝试复制连接 url 并替换为以下内容
url=jdbc:h2:file:./target/test
对其他设置执行相同的操作
Liquibase maven 插件支持通过pom.xml 配置注入。
所以如果你用的是application.yml,那么你可以使用properties-maven-plugin to include your properties from application.properties (or use yaml-properties-maven-plugin),然后将它们注入到liquibase配置中:
示例:
<plugin>
<groupId>it.ozimov</groupId>
<artifactId>yaml-properties-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>src/main/resources/application.yml</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
现在您可以在 liquibase 配置中注入这些属性:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<changeLogFile>src/main/resources/db/changelog/db.changelog-master.yaml</changeLogFile>
<driver>${spring.datasource.driverClassName}</driver>
<url>${spring.datasource.url}</url>
<username>${spring.datasource.username}</username>
<password>${spring.datasource.password}</password>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<databaseChangeLogTableName>DATABASECHANGELOG</databaseChangeLogTableName>
<databaseChangeLogLockTableName>DATABASECHANGELOGLOCK</databaseChangeLogLockTableName>
</configuration>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
</plugin>
我还需要设置 logicalFilePath 以确保 spring 引导集成和 Maven 插件推断的更新日志路径相同。
我正在学习 Liquibase 和 Spring Boot,所以我用 Spring Initializr.
创建了一个简单的项目在我添加的 POM.xml 文件中:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/application.properties</propertyFile>
</configuration>
</plugin>
我已将 application.properties 指定为 属性 文件,因此我的应用程序的所有配置都可以在一个文件中进行。
当我 运行 来自 IntelliJ 的任何 liquibase-maven-plugin 任务时,我得到不同的错误,这是一个示例 运行 执行 changeLogSync 任务:
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.4.1:changelogSync (default-cli) on project simpleTest: The changeLogFile must be specified
如果我在 application.properties 中添加正确的键,我就能让它工作。
例如,我发现 liquibase-maven-plugin 不会读取 spring.datasource.url 属性 但它只会读取 url 属性.
出于这个原因,我的 application.properties 必须是类似的东西:
environment = JUnit
spring.datasource.url = jdbc:h2:file:./target/test
spring.datasource.driver-class-name = org.h2.Driver
spring.datasource.username = sa
spring.datasource.password = sa
spring.liquibase.change-log = classpath:/db/changelog/db.changelog-master.yaml
spring.h2.console.enabled = true
spring.h2.console.path = /h2-console
# Keys needed for liquibase maven plugin
url = jdbc:h2:file:./target/test
username = sa
password = sa
如果我遵循这种模式,我最终会得到几个名称略有不同但在我的 application.properties 中具有相同值的键,这个解决方案显然非常丑陋且效率低下。
在 Spring 引导中配置和使用 Liquibase Maven 插件的有效且可维护的方法是什么?
在收到 Amith Kumar 的回答后进行编辑:
environment=JUnit
spring.datasource.url=jdbc:h2:file:./target/glossary-test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.yaml
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
url=${spring.datasource.url}
changeLogFile=${spring.liquibase.change-log}
username=${spring.datasource.username}
password=${spring.datasource.password}
编辑后出错:
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.4.1:dropAll (default-cli) on project test: Error setting up or running Liquibase: liquibase.exception.DatabaseException: java.lang.RuntimeException: Cannot find database driver: Driver class was not specified and could not be determined from the url (${spring.datasource.url}) -> [Help 1]
在很多项目中很常见。
当您使用多个 plug-ins/library 时,每个都期望环境配置中的某些属性,其中键名以其本机命名法定义。
这个问题没有标准化。
为了避免为多个属性提供相同的值,容易出错,建议您使用引用。
# Keys needed for liquibase maven plugin
url=${spring.datasource.url}
更新
我注意到当 运行 liquibase maven 插件当然在 spring 上下文之外运行时,您遇到了异常。我之前提供的解决方案适用于 spring 上下文,即当您启动应用程序时。
对于给定的场景,使用 maven filter resource files 特性。所以你的命令会变成
mvn liquibase:generateChangeLog resources:resources
您的设置如下所示:
src/main/filters/filter.properties
db.url=jdbc:h2:file:./target/glossary-test
db.username=sa
db.password=sa
db.driver=org.h2.Driver
db.lb.changeLogFile=classpath:/db/changelog/db.changelog-master.yaml
application.properties
spring.datasource.url=@db.url@
spring.datasource.username=@db.username@
spring.datasource.password=@db.password@
spring.datasource.driver-class-name=@db.driver@
url=@db.url@
username=@db.username@
password=@db.password@
driver=@db.driver@
changeLogFile=@db.lb.changeLogFile@
pom.xml
<build>
......
<plugins
......
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<propertyFile>target/classes/application.properties</propertyFile>
</configuration>
</plugin>
</plugins>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
请参阅我的 github project 以获得完整的工作解决方案。查看 filter.properties
文件,其中定义了通用属性,然后在 application.properties
文件中引用了相同的属性。
NOTE: Since this is a spring project, you can't use
${propertyName}
for maven filter file as its reserved property placeholder syntax for spring, but then use@propertyName@
. For non-spring project${propertyName}
will work out of the box.
application.properties
设置非常快,可以启动 运行 应用程序,但在灵活性方面不是最佳解决方案
我的建议是使用 @Configuration
配置数据源,例如 here
然后配置上面定义的liquibase传递数据源如下
@Configuration
public class LiquibaseConfigurer {
@Autowired
@Qualifier("primaryDataSource")
private DataSource oltpDataSource;
@Bean
@DependsOn
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setChangeLog("classpath:liquibase/liquibase-changelog.xml");
liquibase.setDataSource(oltpDataSource);
return liquibase;
}
}
在这种情况下,您只需要 liquibase-core
如下依赖关系
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
一个更简单的替代方法是在没有 maven 插件的应用程序外部配置 liquibase。
下载库,或使用一些包管理器安装它,然后启动包含所有设置的命令行
liquibase --driver=org.h2.Driver \
--classpath=/path/to/h2/driver.jar \
--changeLogFile=/db/changelog/db.changelog-master.yaml \
--url="jdbc:h2:file:./target/glossary-test" \
--username=sa \
--password=sa \
--logLevel=debug \
migrate
无论如何,你现在遇到的问题是因为你写了这个:
url=${spring.datasource.url}
我不知道你在哪里找到这个语法,但尝试复制连接 url 并替换为以下内容
url=jdbc:h2:file:./target/test
对其他设置执行相同的操作
Liquibase maven 插件支持通过pom.xml 配置注入。
所以如果你用的是application.yml,那么你可以使用properties-maven-plugin to include your properties from application.properties (or use yaml-properties-maven-plugin),然后将它们注入到liquibase配置中:
示例:
<plugin>
<groupId>it.ozimov</groupId>
<artifactId>yaml-properties-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>src/main/resources/application.yml</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
现在您可以在 liquibase 配置中注入这些属性:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<changeLogFile>src/main/resources/db/changelog/db.changelog-master.yaml</changeLogFile>
<driver>${spring.datasource.driverClassName}</driver>
<url>${spring.datasource.url}</url>
<username>${spring.datasource.username}</username>
<password>${spring.datasource.password}</password>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<databaseChangeLogTableName>DATABASECHANGELOG</databaseChangeLogTableName>
<databaseChangeLogLockTableName>DATABASECHANGELOGLOCK</databaseChangeLogLockTableName>
</configuration>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
</plugin>
我还需要设置 logicalFilePath 以确保 spring 引导集成和 Maven 插件推断的更新日志路径相同。