为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕斯709654 2024-01-17 20:50:59
我正在设置一个发布流程,以尽可能轻松地升级我们的生产环境。为了实现数据库方面的目标,我选择了 liquibase。每次环境升级时:代码交付到服务器上,mvn liquibase:diff运行以生成先前版本的变更日志mvn spring-boot:run运行以启动应用程序并使用新的变更日志执行 liquibase,因此,从新交付的代码实体调整数据库。问题是,例如,如果将java 中的字段移动到其他实体,liquibase将删除该列,而不将数据传输到新的字段位置。@Entity所以我的问题是,我们可以配置 liquibase 来避免列和表删除吗?为了能够将数据复制到新位置,然后有效地永久删除列(或表)?我们使用spring-boot 2.1.2和liquibase maven 插件 3.4.1。我们的数据库是MySQL 5.7.27。我试图找到如何导出一个中的所有数据库创建/更改 以及另一个中的所有数据库创建/更改。就像我们可以在这两个之间执行,第三个专门用于将数据复制到新位置。Bu 在 liquibase 文档中没有找到解决方案:https://www.liquibase.org/documentation/diff.htmlchangeSetchangeLog.xml changeSetchangeLog.xmlchangeLogchangeLog为了说明我的例子:v1:@Entitypublic class Person {     private long id;     private String name;     private String phoneNumber;}成为v2 : (创建实体Phone来替换实体Person的字段phoneNumber )@Entitypublic class Person {     private long id;     private String name;     private Phone phone;}@Entitypublic 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 来实现这一目标?
查看完整描述

1 回答

?
森林海

TA贡献2011条经验 获得超2个赞

也许我错过了一些东西,但据我了解,这diff并不是万能的工具,可以免除您的任何责任。

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

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

理论上,差异工具还可以检查数据库之间的新数据、更新数据和丢失数据,但实际上这不起作用,原因有两个:

  • 表现。随着数据集的增长,要比较的信息量也会不断增加,直至无法管理。

  • 更改数据。在开发过程中,测试数据通常会添加到开发数据库中,而这些数据不应复制到其他数据库中。此外,新数据可能会添加到测试和生产数据库中,但不应仅仅因为开发数据库中不存在这些数据而将其删除。

对于你的情况,我会做这样的事情:

  1. 创建一个新表phone

  2. 添加栏目person.phone_id

  3. 将数据从 复制person.phone_numberphone.phone_number

  4. 将数据从 复制phone.idperson.phone_id

  5. person在和之间创建外键约束phone

  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"/>


查看完整回答
反对 回复 2024-01-17
  • 1 回答
  • 0 关注
  • 32 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信