java - 使用 mvn liquibase :diff? 时如何禁用删除表和列

标签 java spring-boot maven spring-data-jpa liquibase

我正在设置发布流程以尽可能轻松地升级我们的生产环境。

为了实现与数据库相关的目标,我选择了 liquibase。 每次升级环境时:

  1. 代码在服务器上交付,
  2. mvn liquibase:diff 运行以生成以前版本的变更日志
  3. mvn spring-boot:run 运行以启动应用程序并使用新的 changeLog 执行 liquibase,因此,根据新交付的代码实体调整数据库。

问题是,例如,如果 java @Entity 中的一个字段移动到另一个实体, liquibase 将删除该列而不会将数据传输到新的字段位置。

所以我的问题是,我们可以配置 liquibase avoid column and table drop 吗?为了能够将数据复制到新位置,然后永久有效地删除列(或表)?

我们正在使用 spring-boot 2.1.2liquibase maven 插件 3.4.1。我们的数据库在 MySQL 5.7.27 上。

我试图找到如何在一个 changeLog.xml 和所有 drop 中导出所有数据库 creation/alteration changeSet changeSet 在另一个 changeLog.xml 中。 这样我们就可以在这两个 changeLog 之间执行,第三个 changeLog 专门用于将数据复制到它们的新位置。 Bu 没有在 liquibase 文档中找到解决方案:https://www.liquibase.org/documentation/diff.html

为了说明我的例子:

v1:

@Entity
public class Person {
     private long id;
     private String name;
     private String phoneNumber;
}

成为

v2: (创建实体 Phone 以替换实体 Person 的字段 phoneNumber)

@Entity
public class Person {
     private long id;
     private String name;
     private Phone phone;
}

@Entity
public class Phone {
    private long id;
    private String phoneNumber;
    private String brand;
}

因此,当 v2 在服务器上交付并运行 mvn liquibase:diff 时,结果 changeLog 将删除 phoneNumber 并在表 person 中创建列 phone。 不从表 person 传输数据,将 phoneNumber 归档到新表 phone 的字段 phoneNumber

我想执行将 Person.phoneNumber 复制到新实体 Phone.phoneNumber 的 changeLog(手动编写)。

这可能吗?或者有什么技巧可以正确地做到这一点?或者也许我以糟糕的方式使用 liquibase 来实现这一目标?

非常感谢!

最佳答案

也许我遗漏了什么,但据我所知,diff 并不是可以免除您任何责任的万能工具。

在某些情况下,您必须自己编写 changeSet,我认为这就是其中之一。

由于 diff 确实是一个非常强大的命令,它也有它的缺点。

查看这篇文章:The Problem With Database Diffs

Theoretically, a diff tool could also check for new, updated, and missing data between database, but in practice this cannot work for two reasons:

  • Performance. As your data set grows, the amount of information to compare grows until it is unmanageable.
  • Changing Data. During development, test data is often added to the development database that shouldn’t be copied into other databases. Also, new data may be added to testing and production databases that should not be deleted just because it doesn’t exist in the development database.

在你的情况下,我会做这样的事情:

  1. 创建一个新表phone
  2. 添加列 person.phone_id
  3. 将数据从 person.phone_number 复制到 phone.phone_number
  4. 将数据从 phone.id 复制到 person.phone_id
  5. personphone 之间创建外键约束
  6. 删除 person.phone_number

代码可能是这样的:

<createTable tableName="phone">
    <column name="id" autoIncrement="true" type="bigserial">
        <constraints primaryKey="true" primaryKeyName="pk_phone"/>
    </column>
    <column name="phone_number" type="varchar(30)"/>
    <column name="brand" type="varchar(255)"/>
</createTable>
<addColumn tableName="person">
    <column name="phone_id" type="bigserial"/>
</addColumn>
<update tableName="phone">
    <column name="phone_number" valueComputed="(select p.phone_nubmer from person p)"/>
</update>
<comment>Assuming that person.phone_number is unique</comment>
<update tableName="person">
    <column name="phone_id" valueComputed="(select p.id from person p where p.phone_number = phone_number)"/>
</update>
<addForeignKeyConstraint baseTableName="person" baseColumnNames="phone_id"
    constraintName="person_phone_id_phone_id_fk"
    referencedTableName="phone" referencedColumnNames="id"/>
<dropColumn tableName="person" columnName="phone_number"/>

关于java - 使用 mvn liquibase :diff? 时如何禁用删除表和列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58625731/

相关文章:

java - Eclipse Oxygen 中的 Spring Boot 项目

java - 在这种情况下,我们需要使用 HttpClient 和其他网络服务

java - 无法一次将多个图像移动到另一个文件夹

java - 为什么 neo4j 的 .db 文件路径无效?

java - 如何在 Maven 2 exec 插件的参数中使用空格

android - 在 Run As -> Android Application 上调用 Eclipse 中的 "Maven Project Builder"(或手动)

java - 阐明:在我的 wadl 中,为什么我的所有资源路径属性都以 "/rest"为前缀?

java - AppEngine Java8 应用程序缺少 appengine-api-1.0

spring-boot - 如何在Gradle中使用Apache CXF + Spring Boot构建SOAP WS?

java - Spring JPA : How to Model Percentage Value