使用 mvn liquibase:diff 时如何禁用删除表和列?
Posted
技术标签:
【中文标题】使用 mvn liquibase:diff 时如何禁用删除表和列?【英文标题】:How to disable drop table and column when using mvn liquibase:diff? 【发布时间】:2020-02-25 18:33:56 【问题描述】:我正在设置发布流程,以尽可能轻松地升级我们的生产环境。
为了实现与数据库相关的目标,我选择了 liquibase。 每次升级环境时:
-
代码在服务器上交付,
运行
mvn liquibase:diff
生成以前版本的changeLog
运行 mvn spring-boot:run
以启动应用程序并使用新的 changeLog 执行 liquibase,从而从新交付的代码实体中调整数据库。
问题在于,如果 java @Entity
中的 字段 被 移动 到另一个实体,liquibase 将删除列而不将数据传输到新的字段位置。
所以我的问题是,我们可以将 liquibase 配置为 avoid 列和表 drop 吗?为了能够将数据复制到新位置,然后有效地永久删除列(或表)?
我们正在使用 spring-boot 2.1.2 和 liquibase maven 插件 3.4.1。我们的数据库位于 MySQL 5.7.27。
我试图找到如何导出所有数据库 creation/alteration changeSet
在一个 changeLog.xml
和所有 drop changeSet
在另一个 @987654328 @。
像这样我们可以在这两个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 将 drop 列 phoneNumber 并创建列 电话在person表中。
在不从表 person 传输数据的情况下,将 phoneNumber 提交到字段 phoneNumber 中的新表 phone。
我想执行将 Person.phoneNumber 复制到新实体 Phone.phoneNumber 的 changeLog(手动编写)。
这可能吗?或者有什么技巧可以正确地做到这一点?或者,也许我正在以不好的方式使用 liquibase 来实现这一目标?
非常感谢!
【问题讨论】:
【参考方案1】:也许我遗漏了一些东西,但据我了解,diff
并不是可以免除您任何责任的万能工具。
在某些情况下,您必须自己编写变更集,我认为这就是其中之一。
由于diff
确实是一个非常强大的命令,它有它的缺点。
查看这篇文章:The Problem With Database Diffs
理论上,差异工具还可以检查新的、更新的和 数据库之间缺少数据,但实际上这不适用于 两个原因:
性能。随着数据集的增长,要比较的信息量也会不断增长,直至无法管理。 更改数据。在开发过程中,测试数据通常被添加到不应复制到其他数据库中的开发数据库中。 此外,新数据可能会添加到测试和生产数据库中 不应该因为它在开发中不存在而被删除 数据库。
在你的情况下,我会做这样的事情:
-
新建表
phone
添加栏目person.phone_id
将数据从person.phone_number
复制到phone.phone_number
将数据从phone.id
复制到person.phone_id
在person
和phone
之间创建外键约束
删除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"/>
【讨论】:
感谢您的回答。我们实际上决定用 changeSets 和一些 sql 脚本自己做更多的事情。我们对旧数据库进行转储,运行 liquibase 以更新架构,最后将数据从转储复制到更新后数据库中的新位置。以上是关于使用 mvn liquibase:diff 时如何禁用删除表和列?的主要内容,如果未能解决你的问题,请参考以下文章
我不明白 liquibase diff 试图通过这些选择来确定啥?
如何在eclipse中使用mvn clean install
当 jenkins 作业作为“执行 Maven 发布”运行时,如何在 shell 步骤中获取参数 MVN_RELEASE_VERSION 的值?