低代码加字段后表结构怎么同步:预览安全 DDL,高风险变更再强制执行

低代码设计器里加了一个字段、把 varchar(32) 拉到 varchar(128),点了保存------业务页面好像有了。 打开库一看:列还是旧的。再点「同步数据库」,弹窗要么灰掉,要么提示「高风险,请导出脚本」。 很多人卡在这里:到底哪些变更能在线跑,哪些必须二次确认?

这篇只跟做一件事:预览差异 → 安全 DDL 直接同步 → 高风险强制执行(仍禁止删表、清空、删列)。 方案载体是 Forge Admin 业务对象设计器;标题用通用词方便检索。文中路径相对仓库 forge-project,推断处标「按源码推演」,发前建议在自己环境用一张非生产表复验。

查重:与已发的 FlowStart 表单挂审批、流程超时终态、门户入口权限都不是同一角度;作废不发的 designPreview 卡死稿也不复用。

TL;DR

  1. 保存设计草稿不等于改库:预览接口只算差异,不执行 DDL(单测 previewNeverExecutesDdl)。
  2. 预览会拆两计数:onlineSafeDdlCount(可在线)与 manualReviewDdlCount(高风险)。
  3. 普通同步:二次确认 confirmOnlineDdl=true 后只跑安全语句(加表、加列、索引、兼容扩容)。
  4. 强制执行:forceExecute=true 可跑预览里的高风险 MODIFY;仍拒绝删表、清空、删列。
  5. 门禁:数据源 allowDdl、权限 ai:lowcode:deploy-ddl、设计版本一致,缺一不可。

一、现象:设计器有字段,库里没有

常见三条「半成品」:

  • 设计器字段面板能看见新列,列表与表单预览也有,但查看建表语句时没有新列。
  • 点同步提示「仅预览 / 人工审核」,或「当前差异均为高风险变更」。
  • 混着加列和改类型:想一次点完,结果安全变更也没落库。

根因通常不是「低代码不能改表」,而是:变更被分成可在线与需审核两类,默认只放行追加式与兼容扩容。 Forge Admin 在提交 da2bf3595 把这件事做透了------先预览计数,再决定「确认同步」还是「强制执行全部」。

二、全景:四步落地

text 复制代码
设计器改字段 / 改长度
        | 保存草稿(不执行 DDL)
        v
POST .../database-diff   -> LowcodeDdlPreviewVO
        | onlineSafeDdlCount / manualReviewDdlCount / warnings
        v
+-------------------+     +----------------------------------+
| 确认同步(安全)     |     | 强制执行全部(含高风险)             |
| confirmOnlineDdl  |     | confirmOnlineDdl + forceExecute  |
| executeSafeDdlOnly|     | executePreviewDdl(..., true)     |
+-------------------+     +----------------------------------+
        |                         |
        +---- 仍禁止破坏性语句 -----+
层级 真实路径
预览 VO .../vo/lowcode/LowcodeDdlPreviewVO.java(onlineSafeDdlCount / manualReviewDdlCount)
白名单 .../lowcode/LowcodeOnlineDdlPolicy.java(isSafeOnlineDdl / assertSafeDdl)
执行 .../lowcode/LowcodeDdlService.java(enrichOnlineSafetyCounts / executeSafeDdlOnly / executePreviewDdl / assertNotDestructiveDdl)
同步门禁 .../businessapp/BusinessObjectTableMappingService.java(syncDatabase confirm/force)
API BusinessObjectDesignerController:POST /{objectId}/database-diff、/database-sync
UI BusinessTableMappingSummary.vue(预览弹窗、确认同步、强制执行全部、导出脚本)
前端 API forge-admin-ui/src/api/business-application.js → syncBusinessObjectDatabase
单测 BusinessObjectDatabaseSyncServiceTest.java(预览不执行、需确认、强制跑高风险等)

权限码:ai:lowcode:deploy-ddl(Controller 上 @SaCheckPermission,Service 内 DDL_PERMISSION 再校验一次)。

三、跟做:从预览到同步

3.1 打开「数据结构」,先预览

在应用中心业务对象设计器展开数据结构面板,点预览差异。前端会先刷新 mapping,再带上当前 designVersion 调差异接口。

同步接口(真正改库时)大致是:

javascript 复制代码
// business-application.js
export function syncBusinessObjectDatabase(objectId, designVersion, options = {}) {
  return request.post("/ai/business/object/" + objectId + "/database-sync", {
    designVersion,
    confirmOnlineDdl: true,
    forceExecute: options.forceExecute === true,
  }, ENCRYPTED_REQUEST)
}

预览走 database-diff,不带执行。后端 previewDatabaseDiff 到 LowcodeDdlService.previewCreateTable,最后 enrichOnlineSafetyCounts:

  • 命中 isSafeOnlineDdl(建表 / 加列 / 加索引 / 注释)→ 计入 safe;
  • 或属于「兼容扩容」集合(同类型加长、放宽或收紧可空等,见 buildCompatibleModifyStatements)→ 也算 safe;
  • 其余(改类型族、缩短长度等)→ manual。

UI 文案会变成类似:「可在线同步 N 条,另有 M 条可强制执行」。

按源码推演:保存设计草稿本身不会执行这些变更------确认弹窗文案写得很直白。漏点同步,页面协议有字段、物理表没有,是预期行为不是玄学。

3.2 安全变更:点「确认同步」

当 onlineSafeDdlCount > 0 且数据源允许在线 DDL 时,主按钮可点。BusinessObjectTableMappingService.syncDatabase 要求:

  1. confirmOnlineDdl == true,否则直接「需要显式二次确认」;
  2. 有 ai:lowcode:deploy-ddl;
  3. designVersion 与当前草稿一致;
  4. 数据源 allowDdl;
  5. 预览 executable == true。

普通同步调用 executeSafeDdlOnly:只执行安全与兼容扩容语句。若同时存在高风险项,状态记 PARTIAL,提示「已在线同步 X 条;另有 Y 条可导出或强制执行」------不会因为一条 unsafe 把整单安全变更挡死。

白名单核心(LowcodeOnlineDdlPolicy.isSafeOnlineDdl)可概括为:

语句形态 是否默认在线安全
建表(含 IF NOT EXISTS) 是
改表加列 是
加普通/唯一索引 是
表/列注释 是
同类型加长、兼容可空变更(兼容集合) 是(按源码:走 compatibleModifies)
改类型族、缩短长度等 否 → manual
删表 / 清空表 / 删列 执行层直接拒绝

3.3 高风险:用「强制执行全部」,或导出给 DBA

预览里 manualReviewDdlCount > 0 时,UI 出现警告色按钮「强制执行全部」。弹窗是 dialog.error,文案明确:可能导致截断或失败,请备份;仍禁止破坏性语句。

后端 forceExecute=true 时走 executePreviewDdl(modelSchema, true):跳过追加式白名单,但仍先 assertNotDestructiveDdl------删表、删列、清空一律抛业务异常。

DTO 注释写清契约:forceExecute 必须与 confirmOnlineDdl=true 同时传入;仍禁止破坏性语句。源码在 assertNotDestructiveDdl 里按语句前缀硬拒绝。

也可以点导出脚本:前端把预览语句拼成 .sql 下载(带表名与 design version 注释),交给 DBA 审核------和生产变更流程兼容。

3.4 和「托管表单自动同步」的差别

页面表单托管存储还会走 syncManagedDatabase:元数据事务提交后自动跑安全 DDL,高风险跳过并记 PARTIAL,不阻断保存。普通业务对象必须走带确认的 syncDatabase------别把「表单自动补列」和「高级数据设置里手动同步」混成一个按钮。

四、对照表:该点哪个按钮

场景 建议动作 结果口径
只加字段 / 新建表 / 加索引 确认同步 期望 IN_SYNC
同类型加长、调整可空 确认同步 走兼容扩容,算安全
加列 + 改类型族混在一起 先确认同步,再强制或导出 先 PARTIAL,再处理 manual
只有缩长度 / 改类型族 强制执行或导出 普通同步会整单拒绝
想删列 / 删表 不要指望在线按钮 执行层拒绝;导出后由 DBA 审

五、自查清单(建议收藏)

  • 运行数据源勾了允许在线 DDL(allowDdl);只读库会预览但不可执行。
  • 账号有 ai:lowcode:deploy-ddl,不只是设计权限。
  • 预览前 designVersion 与草稿一致;过期版本同步会被拒。
  • 先看 onlineSafeDdlCount / manualReviewDdlCount,再决定按钮。
  • 普通同步成功但状态 PARTIAL:去处理剩余高风险,或导出脚本。
  • 强制执行前已备份;接受截断/失败风险。
  • 任何入口都执行不了删表/清空------这是特性不是 bug。
  • 非生产表先复验一遍;生产大表评估锁表窗口(平台不替代 gh-ost)。

五(续)、跟做小场景:加列 + 改长度混单

假设业务对象已有物理表,你在设计器做了两件事:新增字段 remark,并把 name 从 varchar(32) 调到 varchar(128)。点预览后常见结果是:

  • onlineSafeDdlCount 至少包含 ADD COLUMN remark;若 name 加长被判定为兼容扩容,也会进 safe。
  • 若你把 name 改成了另一类型族(例如改成 text 或整型),则这条进 manualReviewDdlCount。

推荐操作顺序:先点「确认同步」把 safe 落库,状态若为 PARTIAL,再决定「强制执行全部」还是导出脚本给 DBA。不要一上来就点强制------把可在线的追加变更也绑进高风险确认,只会增加误操作面。

常见坑(按源码行为)

  1. 只保存设计、不同步:列表协议有字段,查询报「未知列」。先看预览计数,再确认同步。
  2. 有设计权、无 deploy-ddl:按钮灰或接口直接拒;找管理员加 ai:lowcode:deploy-ddl。
  3. 数据源未开 allowDdl:预览能出语句,执行口直接关;只读备库常见。
  4. designVersion 过期:别人刚发过版或你本地草稿已变;刷新映射后再预览。
  5. 把托管表单的自动补列,当成高级数据设置的手动同步:两条链路门禁不同,混用会误判「怎么有时自动有时要确认」。

若你维护的是生产大表,即使语句落在 safe 白名单,也建议先在预发用同等数据量估锁表窗口;Forge Admin 提供的是设计器侧的门禁与分账,不是在线改表引擎本身(不替代第三方在线变更工具)。把「能不能点」和「该不该在高峰点」分开看,运维会轻松很多。

六、小结 & CTA

低代码「加字段」真正落地,靠的不是一个万能改表语句,而是三道闸:

  1. 预览分账:安全条数 vs 高风险条数摊在桌面上;
  2. 默认同步只追加/兼容扩容,避免一条 unsafe 拖死整单;
  3. 强制执行有二次确认,破坏性语句永拒。

如果你也在做「设计器改模型 → 物理表跟着变」,欢迎对照这套门禁看自己的平台缺了哪一闸。觉得有用请点赞收藏,少在测试库误跑一条缩长度;评论区可以丢你卡过的 DDL 场景,我按票数排下一篇跟做。

相关推荐
搭贝1 小时前
【无标题】
人工智能·低代码·ai·1024程序员节·搭贝
huaweichenai1 小时前
spring boot对接kafka实现消息队列处理
spring boot·后端·kafka
简简单单就是我_hehe1 小时前
一次 ClickHouse 服务器磁盘告警的排查与修复实录
java·服务器·前端
Thomas.Sir1 小时前
第11课:文件上传下载、跨域CORS配置,SpringBoot4.x跨域新方案
java·spring boot
wuminyu1 小时前
JVM规范学习总结:class执行性能差异
java·linux·c语言·jvm·c++
一条泥憨鱼2 小时前
【RabbitMQ】高级篇
java·分布式·rabbitmq·php·ruby
京师20万禁军教头2 小时前
50-常用类-Arrays
java
寰梦2 小时前
Spring Boot + MinIO 大文件上传完整实战:MD5 秒传、分片上传、断点续传与引用一致性
java·spring boot·文件上传·minio
行者-全栈开发2 小时前
【码动四季·秋】把 Spring Boot 的 Tomcat 换成 Undertow:一次容器替换的三处暗坑
spring boot·tomcat·容器化·依赖管理·undertow