数据库变更

Database schema migration,数据库变更,是根据你的应用程序数据模型的变化更新数据库 schema 的过程。

Jmix 使用 Liquibase 作为数据库变更工具。

工作流程

Jmix Studio 将 JPA 实体 的当前状态和相应 数据存储 的数据库 schema 进行比较,然后以 Liquibase 更改日志的格式创建变更脚本。当你使用 Run/Debug Configuration 启动应用程序时,会自动执行这个过程。更改日志保存在应用程序的源代码中,并构建到二进制制品中。

还可以通过修改 Run/Debug configuration 设置禁用自动创建变更脚本的功能。

当应用程序启动时,会使用 Liquibase 运行生成的更改日志以更新连接的数据库。

你还可以随时使用 Generate Diff Changelog 操作创建更改日志,并在 Studio 的 Jmix tool 窗口中对数据存储执行 Update 操作。

应用程序所依赖的模块也可以包含 Liquibase 更改日志文件。依赖项的更改日志在应用程序的更改日志之前运行到你的数据库上。

变更日志文件结构

Studio 在应用程序项目的 src/main/resources/<base_package>/liquibase 目录下生成变更日志文件。在此目录中,Studio 为主数据存储创建 changelog 目录,并为附加数据存储创建 <store>-changelog 目录。更改日志文件创建在以与当前日期的年月命名的子目录下。文件名包括日期、当天的序列号和一个随机字符序列,以避免多个开发人员在同一个项目上工作时发生冲突。

对于每个数据存储,在 src/main/resources/<base_package>/liquibase 目录中都有一个主变更日志文件。其中包含一个指令,用于包含在 changelog 子目录下所有生成的变更日志文件。当应用程序或 Studio 执行数据库变更时,主变更日志文件将传递给 Liquibase。

src/main/resources/datamodel/ex1/
├── liquibase/ (1)
│   ├── changelog/ (2)
│   │   ├── 010-init-user.xml (3)
│   │   └── 2020/
│   │       ├── 11/
│   │       │   ├── 12-010-fe2b82e6.xml (4)
│   │       │   └── 27-010-fe2b82e6.xml
│   │       └── 12/
│   │           └── 17-010-fe2b82e6.xml
│   ├── changelog.xml (5)
│   ├── locations-changelog/ (6)
│   │   └── 2020/
│   │       └── 11/
│   │           ├── 25-010-fe2b82e6.xml
│   │           └── 28-010-fe2b82e6.xml
│   └── locations-changelog.xml (7)
1 Liquibase 变更日志文件结构的根目录。
2 主数据存储的变更日志目录。
3 为新项目提供的变更日志文件。为 User 实体创建一个表。
4 Studio 生成的变更日志文件。
5 主数据存储的主变更日志文件。
6 locations 数据存储的变更日志目录。
7 locations 数据存储的主变更日志文件。

可以手动编写 Liquibase 更改日志文件并将它们放入上述结构中。Liquibase 按带有整个路径的字母顺序执行包含的变更日志,因此,需要为自定义文件设置合适的文件名。

切勿删除主 changelog.xml 文件,这是启动变更过程必需的文件。此外,除非你想以非标准方式实现安全性,否则不要删除 changelog/010-init-user.xml

配置 Liquibase

可以按照 Spring Boot 文档(参见 spring.liquibase. 属性)中相同的方式在 application.properties 中为主数据存储设置 Liquibase 属性(参见 spring.liquibase. 属性),但需要将 spring.liquibase 前缀替换为 jmix.liquibase,例如:

jmix.liquibase.enabled = false
不能更改 change-log 属性,因为框架始终将其设置为主更改日志。

默认情况下,Jmix Studio 会将数据库中的所有表与数据模型进行比较,并生成数据库变更脚本,脚本中对无法找到对应实体类的数据库表还会生成 DROP TABLE 语句。如果你的数据库包含无法与实体对应的表,可以将表格前缀或完整名称添加到 main.datasource.studio.liquibase.excludePrefixes 应用程序属性,这样可以忽略这些表,例如:

main.datasource.studio.liquibase.excludePrefixes = abc_,foo,bar

对于 附加数据存储,将应用程序属性中的 main 替换为此数据存储的名称。

如果要开放 附加数据存储 的 Liquibase 属性,请按下面的示例更改配置:

@Bean
@ConfigurationProperties(prefix = "locations.liquibase")
public LiquibaseProperties locationsLiquibaseProperties() {
    return new LiquibaseProperties();
}

@Bean
public SpringLiquibase locationsLiquibase(LiquibaseChangeLogProcessor processor) {
    return JmixLiquibaseCreator.create(locationsDataSource(),
            locationsLiquibaseProperties(), processor, "locations");
}

这样,将能够通过 locations.liquibase 前缀在 application.properties 中设置 locations 数据存储的 Liquibase 属性。