JVS低代码动态建表原理:从模型配置到数据库DDL的生成逻辑
如果默认类型不满足需求(如需要GIS地理类型),可通过插件机制注册:实现接口。在中注册。前端组件库中增加对应的编辑器。示例:注册PostgreSQL的GEOMETRY类型:java@Override@OverrideJVS低代码的动态建表引擎通过模型驱动DDL生成、非破坏性变更检测、版本快照回滚等设计,实现了生产环境可靠的零代码表结构管理。开发者可直接复用此机制,或二次开发自定义字段类型。
摘要区:
JVS低代码的数据模型引擎无需手动建表,通过可视化配置自动生成数据库表结构。本文从源码层面解析其实现:模型配置JSON如何转换为DDL语句,如何处理字段类型映射、索引、外键,以及版本升级时的增量变更策略。
一、问题的提出
传统开发中,每新增一个业务模块,都需要手动编写CREATE TABLE、ALTER TABLE等DDL语句,并与实体类保持同步。JVS低代码的数据模型引擎实现了“配置即表结构”的能力,其核心挑战在于:
-
如何将用户拖拽配置的字段(文本、数字、日期、选项等)映射为MySQL/PostgreSQL等数据库的数据类型?
-
如何保证模型修改后,存量数据不丢失?
-
如何处理字段重命名、删除等破坏性操作?
本文将以JVS低代码v2.5源码为基础,分步骤解析动态建表的完整逻辑。
二、整体流程概览
用户在前端配置数据模型 → 保存模型JSON → 后端解析 → 生成Diff变更计划 → 执行DDL → 更新模型版本号。
核心类位于 jvs-modules/data-model 模块:
text
com.jvs.dm.service.ModelDDLService ├── generateCreateDDL() // 新建模型时生成CREATE TABLE ├── generateAlterDDL() // 修改模型时生成ALTER TABLE ├── columnTypeMapping() // 类型映射 └── executeWithVersion() // 执行DDL并记录版本
三、关键源码解析
3.1 字段类型映射规则
JVS定义了一套抽象数据类型(JvsFieldType),然后根据数据库方言转换:
java
public enum JvsFieldType { TEXT, // 短文本 → VARCHAR(255) LONG_TEXT, // 长文本 → TEXT NUMBER, // 数字 → DECIMAL(20,4) INTEGER, // 整数 → BIGINT DATE, // 日期 → DATE DATETIME, // 日期时间 → DATETIME(3) BOOLEAN, // 布尔 → TINYINT(1) OPTION, // 选项 → VARCHAR(100) FILE, // 附件 → VARCHAR(500) 存储路径 REFERENCE; // 关联 → BIGINT 存储关联ID }
转换核心代码(简化版):
java
public String toColumnDefinition(JvsField field, Dialect dialect) { String type = field.getType().getSqlType(dialect); StringBuilder sb = new StringBuilder(); sb.append(field.getName()).append(" ").append(type); if (field.isRequired()) sb.append(" NOT NULL"); if (field.getDefaultValue() != null) sb.append(" DEFAULT '").append(field.getDefaultValue()).append("'"); return sb.toString(); }
3.2 Diff算法:模型变更检测
当用户修改模型(新增/修改/删除字段)时,引擎会比较旧模型JSON与新模型JSON,生成变更列表:
java
public List<SchemaChange> diff(Model oldModel, Model newModel) { List<SchemaChange> changes = new ArrayList<>(); // 新增字段 for (Field newField : newModel.getFields()) { if (oldModel.getField(newField.getName()) == null) { changes.add(new AddColumnChange(newField)); } } // 删除字段:将字段标记为deleted(不实际删除列,避免数据丢失) for (Field oldField : oldModel.getFields()) { if (newModel.getField(oldField.getName()) == null) { changes.add(new SoftDeleteColumnChange(oldField)); } } // 修改字段(类型、长度、是否必填) // ... 使用比较器 return changes; }
实际执行DDL时,对删除字段的处理:
-
不执行
DROP COLUMN,而是重命名为{field_name}_deleted_{timestamp},并记录到deleted_columns元数据表中。 -
这样既避免了数据丢失,又允许用户随时恢复。
3.3 版本控制与回滚
每次执行DDL后,系统会在 jvs_model_version 表中记录:
| 字段 | 说明 |
|---|---|
| model_id | 模型ID |
| version | 版本号(自增) |
| ddl_sql | 执行的DDL语句 |
| schema_snapshot | 完整表结构的JSON快照 |
| created_at | 执行时间 |
用户可通过管理后台回滚到任意历史版本,系统会根据 schema_snapshot 反向生成回滚DDL。
四、扩展实践:自定义字段类型
如果默认类型不满足需求(如需要GIS地理类型),可通过插件机制注册:
-
实现
CustomTypeHandler接口。 -
在
resources/META-INF/services/com.jvs.dm.CustomTypeHandler中注册。 -
前端组件库中增加对应的编辑器。
示例:注册PostgreSQL的 GEOMETRY 类型:
java
public class GeometryTypeHandler implements CustomTypeHandler { @Override public String getTypeName() { return "GEOMETRY"; } @Override public String toSqlType(Dialect dialect) { return "GEOMETRY"; } }
五、总结
JVS低代码的动态建表引擎通过模型驱动DDL生成、非破坏性变更检测、版本快照回滚等设计,实现了生产环境可靠的零代码表结构管理。开发者可直接复用此机制,或二次开发自定义字段类型。
更多推荐




所有评论(0)