我正在设置发布流程以尽可能轻松地升级我们的生产环境。
为了实现与数据库相关的目标,我选择了 liquibase。 每次升级环境时:
- 代码在服务器上交付,
mvn liquibase:diff
运行以生成以前版本的变更日志mvn spring-boot:run
运行以启动应用程序并使用新的 changeLog 执行 liquibase,因此,根据新交付的代码实体调整数据库。
问题是,例如,如果 java @Entity
中的一个字段被移动到另一个实体, liquibase 将删除该列而不会将数据传输到新的字段位置。
所以我的问题是,我们可以配置 liquibase avoid column and table drop 吗?为了能够将数据复制到新位置,然后永久有效地删除列(或表)?
我们正在使用 spring-boot 2.1.2 和 liquibase 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.
在你的情况下,我会做这样的事情:
- 创建一个新表
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"/>
关于java - 使用 mvn liquibase :diff? 时如何禁用删除表和列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58625731/