问题描述
我一直在尝试使用 liquibase 来管理 Spring JPA 项目上的迁移,就像 Python/Django 对 makemigrations
所做的那样。 Liquibase documentation 非常令人困惑,我尝试遵循我在网上找到的一些 SA 答案和教程,但都无济于事。
这是我想要做的:
到目前为止,我能够生成一个“差异”更改日志文件,并以某种方式设法让 liquibase 在空数据库上创建 databasechangelog
和 databasechangeloglock
表。但是,我无法使用差异更新 master.xml
文件或将差异应用于数据库。
到目前为止,这是我的配置(基本的 spring-jpa 项目,只有一个用于测试的实体):
Pom.xml(缩写)
<project>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>my-group</groupId>
<artifactId>web</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>MysqL</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>4.3.2</version>
<configuration>
<changeLogFile>src/main/resources/db/changelog-master.xml</changeLogFile>
<diffChangeLogFile>src/main/resources/db/diff-changelog.xml</diffChangeLogFile>
<outputChangeLogFile>src/main/resources/db/out-changelog.xml</outputChangeLogFile>
<driver>com.MysqL.jdbc.Driver</driver>
<referenceUrl>hibernate:spring:my.project.model?dialect=org.hibernate.dialect.MysqL5Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy</referenceUrl>
<url>jdbc:MysqL://localhost:3306/my-db?useSSL=false</url>
<username>user</username>
<password>pass</password>
<outputDefaultSchema>true</outputDefaultSchema>
</configuration>
<dependencies>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate5</artifactId>
<version>4.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.27.0-GA</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MysqL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=none
spring.datasource.driver-class-name=com.MysqL.jdbc.Driver
spring.datasource.url = jdbc:MysqL://localhost:3306/my-db?useSSL=false
spring.datasource.username = user
spring.datasource.password = pass
spring.liquibase.enabled=true
spring.liquibase.url=jdbc:MysqL://localhost:3306/my-db?useSSL=false
spring.liquibase.user=user
spring.liquibase.password=pass
spring.liquibase.change-log=classpath:db/changelog-master.xml
logging.level.org.springframework=INFO
hibernate.dialect=org.hibernate.dialect.MysqL5InnoDBDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
hibernate.generate_statistics=true
我还添加了一个空的 changelog-master.xml 文件,其中包含(不包括命名空间):
<databaseChangeLog />
因此,如果我运行 spring-boot:run
,它会创建这两个 databasechangelog 表。(无内容)。然后我可以运行 mvn liquibase:diff
生成一个 diff.xml 文件(尽管有一些休眠警告)。这个 diff 文件对我很有意义:
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog>
<changeSet author="tiago (generated)" id="1618352585193-1">
<createTable tableName="chunk">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="chunkPK"/>
</column>
<column name="x_origin" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="y_origin" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
但是现在,我该如何应用它?我如何使该 diff 命令将此特定差异“附加”到主更改日志?运行 mvn liquibase:update
什么也不做。此外,数据库上的变更日志表保持为空。
<databaseChangeLog>
<include file="classpath:db/diff-changelog.xml" />
</databaseChangeLog>
在运行 changelogSync
和 update
后,我设法在 databasechangelog
表上获得了一条记录。但是新表并未创建。
感谢您的帮助,
解决方法
如果 Liquidbase 使您感到困惑,也许您应该考虑使用其他迁移工具。我个人使用 flyway,它非常直观且易于使用。 Flyway 只使用 SQL,这似乎很适合 MySQL。
,你可以查看我写的这个演示:https://github.com/AlexeyGorelik/liquibase-demo
这里我使用纯 liquibase core-lib 和 .xml 方法(个人更喜欢 .yml,因为它对我来说更具可读性)。
如何运行:
- 运行 DemoApplication 类,Liquibase bean 将完成剩下的工作。
- 通过 http://localhost:8080/customer/1 检查实体是否存在
不要忘记检查数据库连接属性!
.sql 文件的文档:https://docs.liquibase.com/change-types/community/sql-file.html