概念

本节解释动态模型(Dynamic Model)背后的主要理念:涉及的实体类型、模型的定义和版本化方式、如何在运行时应用变更、数据存储位置以及支持的数据库。

静态实体与动态实体

动态模型区分两种实体:

  • 静态实体 是应用程序中的常规实体。被编译为 Java 类,在类路径中使用。

  • 动态实体 在运行时定义,由框架生成。不存在于应用程序源代码中。

静态实体和动态实体都可以添加动态属性。也就是说,既可以用新属性丰富已有的应用程序实体,也可以独立地引入仅在运行时存在的全新实体。

模型定义

动态模型是枚举、实体、属性和视图的声明性描述。可以在管理 UI 中以图形方式编辑:创建实体、添加带有类型和约束的属性、定义枚举,以及声明视图和菜单项。

在后台,动态模型被序列化为 YAML。在使用图形化编辑器工作时,不直接编辑 YAML,但 YAML 形式便于审查、导出和导入。有关文件中元素、支持的值和默认值的完整列表,请参见 YAML 参考。

版本化与部署

模型定义作为一组版本化配置存储在数据库中。每次部署会保存一个新版本,只能有一个版本处于激活状态。之前的版本都会保留,可以在 模型历史 里查看。若要退回一个早期的版本,可以从历史里复制其 YAML 然后重新部署。

应用程序启动时,框架可以自动使用激活的版本,从而运行中的应用程序能反映最新部署的模型。此行为由 jmix.dynmodel.deploy-on-app-start 属性控制。

应用变更

当模型变更时,框架会从新的模型定义生成 模型元数据 并进行原子化发布。在发布完成之前,运行中的应用程序会继续使用前一个发布的内容,因此,发布失败不会造成仅更新部分模型的问题。

破坏性清理(例如删除不再属于模型的列或表)会延迟执行,直到不再有任何工作使用前一个发布时为止。这可以在模型变更时保持正在运行的工作的一致性。

已打开的视图不会自动切换,需要重新加载后才会获取变更。

框架还会检查在打开模型编辑时,没人发布其他的模型。如果有人在你编辑过程中发布了,则会拒绝你的发布,从而不会静默覆盖别人的改动。此时,需要你重新加载模型配置并重复你个改动。

集群

Jmix 3.1+

动态模型可以在应用程序集群中运行。当启用集群支持时:

  • 在一个节点发布的模型会发布至其他节点,无需重新启动。

  • 整个集群中,同一时刻只能运行一个发布。如果一个用户尝试发布一个正在其他节点发布的模型,则会拒绝当前的发布,并告知用户此时谁正在发布模型。需要等待对方完成后再尝试。

启用集群支持:

  1. 将 jmix.dynmodel.cluster.enabled 属性设置为 true。

  2. 将 悲观锁 扩展组件添加到项目。其中包含集群的发布锁。如果启用了集群支持而缺少该扩展组件,应用程序不会启动。

  3. 按照 集群通信 中的说明配置节点之间的集群通信。已发布模型和发布锁的消息都需要走这个通道。如果没配置,则在一个节点上发布的模型只有在其他节点重启时才会到达。

jmix.dynmodel.cluster.apply-lock-timeout-sec 属性设置发布期间持有发布锁的节点停止的超时时限。请将其设置为大于应用程序中最长发布耗时的值。

存储

动态模型将运行时数据保存在特定的数据库表中:

  • 静态 实体的动态属性存储在单独的 侧表(side table) 中。默认情况下,侧表的名称使用 DYN_ 前缀,并在其所属静态实体的同一物理数据存储中创建。

  • 动态 实体拥有自己的 专用表,默认也使用 DYN_ 前缀,主键列为 DYNMOD_ID。

每个实体可以通过其 store 属性指定物理存储;当省略时,实体使用 main 数据存储。实体引用和实体集合属性仅支持在同一物理存储的实体。

表名前缀是可配置的;相关设置请参见 YAML 参考 和 应用程序属性。

数据工具

Jmix 3.1+

动态实体和动态属性显示在 数据工具 扩展组件的视图中:

  • 数据模型 视图中显示动态实体及其数据存储和表,以及静态实体的动态属性及其副表列。计算属性和集合属性也列出,但是没有表格列。图表会显示哪些实体和属性是动态的。

  • 实体探查 支持浏览、创建、编辑和删除动态实体的实例,并编辑静态实体的动态属性。可以在通用过滤器中按动态属性进行过滤和排序。

支持的数据库

动态模型支持以下数据库:

  • HSQLDB

  • H2

  • PostgreSQL

  • MySQL 8+

  • MariaDB 10+

  • MS SQL Server 2012+

  • Oracle 12.2+