输出文件
数据库迁移有 2 个输出文件
- 迁移模型 XML - 这具有模型的逻辑差异,作为
apply
或pendingDrops
更改集 - 应用 SQL - 这是应用更改的 DDL 脚本
当运行 DbMigration 时,它会加载任何先前的迁移 xml,并将它们组合在一起以定义先前的模型,然后将其与现有的实体 bean 进行比较。
待处理的删除
仅将非破坏性更改包含在 apply
中,而 drop table
和 drop column
等更改则放入 pendingDrops
changeSet 中。
需要明确选择待处理的删除更改才能进入迁移。
鉴于应用程序在集群环境中运行,待处理的删除通常需要至少 1 次迁移才能跟踪正常的应用更改。此延迟可能是几分钟、几天,并且某些删除可能永远不会运行。
迁移 xml
当运行 DbMigration 时,将确定模型的 diff
并将其输出为迁移模型 xml 文档。此差异可以有 apply
更改或 pendingDrops
更改。
从迁移 apply
changeSet 中生成将应用的实际 DDL。
逻辑更改
请注意,迁移 xml 中的更改与数据库无关,并且可以将单个迁移 xml 文档用于为多个数据库生成迁移 DDL。例如,您可以从单个迁移 xml 为 Postgres、Oracle 和 SQL Server 生成迁移 DDL 脚本。在迁移 xml 中,您将看到逻辑类型,如 JSON 类型(在数据库中存储 JSON 文档),对于 Postgres,这可以转换为 JSONB,对于 Oracle,这可以转换为 CLOB。
更改在逻辑上也是“逻辑的”,因为对具有 @History 和 @Draftable 的实体所做的更改通常会转换为多个更改。例如,向 @History 实体添加属性可能会向基本表添加列,向历史记录表添加列,并根据需要更改触发器。
迁移 xml 示例
以下是使用 apply
更改生成的迁移 xml 示例。客户表已向其中添加了 2 个新列。
如果客户表具有 @History 支持,则这还可能向历史记录表添加列并更新关联的数据库触发器。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
<changeSet type="apply">
<addColumn tableName="customer">
<column name="registered" type="date"/>
<column name="comments" type="varchar(1000)"/>
</addColumn>
</changeSet>
</migration>
具有 pendingDrops 的迁移示例
以下是使用 pendingDrops
更改生成的迁移 xml 示例。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
<changeSet type="pendingDrops">
<dropColumn columnName="shortTitle" tableName="document" withHistory="true"/>
</changeSet>
</migration>
除非显式选择,否则不会将待定删除更改合并到 apply DDL 脚本中。一旦应用了待定删除,它们就会从“待定删除”列表中删除。
应用 DDL
apply ddl 脚本包含我们要应用到数据库的更改。这是您让 FlywayDB 或类似工具运行的 DDL 脚本。
应用待处理的删除
INFO c.a.ebean.dbmigration.DbMigration - Pending un-applied drops in versions [1.2]
数据库迁移将记录 INFO
级别消息,说明哪些迁移包含尚未应用的待定删除。在某个时间点,决定将其中一个待定删除作为下一个迁移应用。
// generate a migration as the drops from migration version "1.2"
System.setProperty("ddl.migration.pendingDropsFor", "1.2");
DbMigration dbMigration = DbMigration.create();
dbMigration.setPlatform(Platform.POSTGRES);
dbMigration.generateMigration();
// generate a migration as the drops from migration version "1.2"
System.setProperty("ddl.migration.pendingDropsFor", "1.2")
DbMigration.create().apply {
setPlatform(Platform.POSTGRES)
}.generateMigration()
然后生成一个迁移,其中 dropsFor
设置为具有我们要应用的待定删除的迁移版本。此外,迁移 apply ddl 包含将执行的各种删除语句。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
<changeSet type="apply" dropsFor="1.2">
<dropColumn columnName="shortTitle" tableName="document" withHistory="true"/>
</changeSet>
</migration>
版本格式
支持的“版本”编号格式与 FlywayDB 版本编号相同,您可以在其中使用“.”或“_”(句点或下划线)作为分隔符。
示例
因此,1.1
和 1_1
都转换为版本 1.1
。
请注意,版本编号控制了执行迁移的顺序,并遵循语义版本控制,因此,例如,1.1.1
将在 1.2
之前执行。通过这种方式,我们可以添加“补丁”迁移。
工作流
如果您使用 Ebean 的迁移运行器来执行迁移,请注意,要运行迁移,要求是必须运行了之前的迁移
。这与 FlywayDB 略有不同,FlywayDB 要求严格的版本号顺序(或者我们可以禁用它以允许任何顺序)。
如果您使用类似于“git flow”的工作流,那么 Ebean 的迁移运行器允许您以非严格顺序处理合并请求。为此而做出的假设是,在存在 2 个或更多合并请求(正在审查,尚未合并到公共 DEV 分支中)的情况下,不会有冲突的数据库迁移更改(如果存在,Ebean 将允许迁移运行,但迁移本身会出错)。
迁移版本和名称
对于迁移,开发人员需要提供version
和name
,可以通过环境变量、系统属性或 ebean.properties 或以编程方式设置这些属性。
System.setProperty("ddl.migration.version", "1.1");
System.setProperty("ddl.migration.name", "support end dating");
System.setProperty("ddl.migration.version", "1.1")
System.setProperty("ddl.migration.name", "support end dating")
离线生成
我们可以在不启动应用程序的情况下以编程方式生成迁移。在src/test/java
中添加带有main 方法
的以下代码。
运行此 main 方法将生成下一个迁移并以offline 模式
启动 Ebean。此离线模式意味着我们无需启动应用程序或需要数据库来生成迁移。
package main;
import io.ebean.annotation.Platform;
import io.ebean.dbmigration.DbMigration;
import java.io.IOException;
public class GenerateDbMigration {
/**
* Generate the next "DB schema DIFF" migration.
*/
public static void main(String[] args) throws IOException {
DbMigration dbMigration = DbMigration.create();
dbMigration.setPlatform(Platform.POSTGRES);
dbMigration.generateMigration();
}
}
import io.ebean.annotation.Platform
import io.ebean.dbmigration.DbMigration
fun main() {
DbMigration.create().apply {
setPlatform(Platform.POSTGRES)
}.generateMigration()
}
运行迁移
你可以使用FlywayDb
、Liquibase
或 Ebean 自带的迁移运行器运行迁移。
Ebean 的迁移运行器
## run migrations when Ebean starts
ebean.migration.run=true
## optionally specify different DB credentials
## to run the migration (own the tables)
datasource.db.adminusername=myDbTableOwner
datasource.db.adminpassword=secret
如果ebean.migration.run=true
,则当 EbeanServer 启动时,它将查看迁移并运行任何需要运行的迁移。默认情况下,迁移运行器将创建一个名为db_migration
的表,该表保存已运行迁移的元数据,并在成功执行迁移时将数据插入此表。
可重复迁移
可重复迁移是特殊迁移,以R__
开头,没有版本号。如果可重复迁移尚未运行或其内容已更改(MD5 校验和已更改),则将运行可重复迁移。
可重复迁移可以包含任何 DDL,但对于 ORM,我们使用它们来定义database VIEWS
,例如使用@View
将实体 bean 映射到数据库视图而不是表。
请参阅展示可重复迁移的第二个视频,其中包含 extra-ddl.xml,并与 @View 一起使用。
FlywayDB 注意事项
要与 FlywayDB 一起使用,我们目前需要使用V
为“版本迁移”添加前缀,以便同时支持“版本迁移”和“可重复迁移”。为此
## must use V prefix on "version migrations" when using FlywayDB
## with both "version" and "repeatable" migrations
ebean.migration.applyPrefix=V