对象存储:数据源加上语义层改动
对象有数据源层和语义层改动两层,叠成当前值;读懂 overridden、sourceGone 和 rev。

本课目标
读完这一课,你将能够
- 说出对象里的两层,以及当前值是怎样合出来的
- 读懂
overridden、sourceGone、rev三个标记 - 判断一次同步或一次改动之后,对象会变成什么样
两层,叠成当前值
上一节的同步只写对象的数据源层。人和智能体通过 Action 做的改动,写在另一层:语义层改动(edits)。两层叠在一起,就是对象的当前值:一个属性有改动就用改动,没有就用数据源的值,两边都没有就是空。应用、搜索、聚合和 SQL 看到的都是当前值。
- 01数据源层只有同步写它
- 02语义层改动Action;开放直接编辑的类型也可由开发者直接写
- 03当前值逐个属性:有改动用改动,否则用数据源
两层互不干扰。MES 里改了工单的交期,没被人改过的属性会跟着变;人改过的属性,仍是人改的值。数据源再同步,冲不掉人的改动。
一个工单的一天
看 WO-1042 这一个工单。一天里发生了四件事:
- 07:30 MES 同步进来
status是running,交期是 10 月 3 日。没有任何改动,当前值全部来自数据源,rev为 1。 - 10:15 计划员执行
hold-work-order车间发现缺料,MES 里还没来得及改。计划员先在 Semantic 里把
status改成paused,并在holdReason(只在 Semantic 里维护的属性)写下「缺料:电机」。这两个属性有了改动,rev变成 2;status的改动盖住了数据源的running,进入overridden。 - 14:00 MES 把工单标成
done数据源层的
status变成done,但当前值仍是paused:改动优先。当前值没变,rev也不变;overridden里status的值更新成数据源现在的done。 - 14:05 MES 把交期改到 10 月 5 日
dueAt没有改动,当前值直接跟着变,rev变成 3。
第四步之后,对象的当前值与编辑标记如下(只列几个属性;这是两层存储示意,不是新对象接口的响应):
{
"type": "workOrder",
"pk": "WO-1042",
"props": { "workOrderNo": "WO-1042", "status": "paused", "dueAt": "2026-10-05T09:00:00Z", "holdReason": "缺料:电机" },
"rev": 3,
"edited": ["status", "holdReason"],
"overridden": { "status": "done" },
"sourceGone": false
}
props 是当前值;edited 列出有改动的属性;overridden 列出被盖住、而且数据源现在是另一个值的属性,连同数据源的值。
这个例子里,改动盖在了一个同步来的属性上。这是允许的,overridden 就是为它设的,但它是例外而不是常态:来自数据源的事实,权威仍在源系统,能在源头改的就去源头改;人在 Semantic 里改的,多是只在这里维护的属性,比如 holdReason、负责人、跟进备注。
三个标记,和几条规矩
被覆盖
改动盖住了数据源的值,而两边不一样,overridden 连同数据源现在的值一起给出。看到它,先问问这个改动还该不该留,尤其是数据源后来又变了的时候。
源头消失
数据源里已经没有这一行(mirror 模式下行从流里消失)。对象默认不出现在搜索、聚合和 SQL 里,改动保留;行回来时对象跟着回来,之前的改动仍然生效。
版本号
当前值每变一次加一。写入时带 ifRev,对不上就返回 409 rev_mismatch,防止后写的盖掉先写的。
用 Action 删除对象,是给它打上「墓碑」:读不到了,数据源不受影响,数据源再送来同一行也不会让它回来。之后再用 Action 新建同一个主键,得到的是新对象,不继承旧的改动。
新 Object Type 缺省只能经 Action 改。只有类型设置 editsConfiguration.onlyAllowPrivilegedEdits: false,开发者才可直接写入或用 --revert 撤掉属性改动:
aidc semantic object workOrder WO-1042 # 当前属性
aidc semantic edits-history workOrder --pk WO-1042 # Action 编辑历史
aidc data update workOrder WO-1042 --revert status --if-rev 3
Action 造成的每一次改动都有记录:谁、什么时候、通过哪个 Action、改成了什么。在对象浏览器的对象视图里能看到这段编辑历史,命令行里用 aidc semantic edits-history workOrder --pk WO-1042,加上 --previous 还能看到改前的值。数据源同步来的变化不在这份历史里。
属性是对象类型定义的一部分。active 属性须先改为 deprecated 或 experimental,提交定义或合并改动后再删除。删掉属性后,它的旧值(包括人改过的)不再出现在当前值里;改类型、改主键同样是破坏性变更,定义时会返回,发布时会记档。发布之前先确认调用它的应用都改好了。
下一节讲这些数据有多新:从源头变化到读到它,时间花在哪里,什么时候才会重新计算。
要点
- 对象有两层:同步写数据源层,Action 写语义层改动。类型开放直接编辑后,开发者也可直接写语义层改动。
- 当前值逐个属性合成:有改动用改动,否则用数据源。
overridden表示改动盖住了数据源的值、两边不一样,并给出数据源现在的值;sourceGone表示数据源里没有这一行;rev随当前值变化加一。- 写入带
ifRev防并发覆盖;只有开放直接编辑的类型,开发者才可用--revert撤掉属性改动。
练一练
算一算当前值
先用纸笔,再拿真实的对象验证。
一个工单起初 plannedQty 是 100。计划员用 Action 改成 80;随后 MES 把它改成 120,并把 status 改成 done。写出这两步之后的 props、edited、overridden 和 rev(起初 rev 是 1,status 是 running)。
在自己的 Semantic 里挑一个被改过的对象,运行 aidc semantic object TYPE KEY 看当前属性,再用 aidc semantic edits-history TYPE --pk KEY --previous 核对 Action 改动。
为 salesOrder 列出哪些属性应该从 ERP 同步,哪些应该只在 Semantic 里维护(例如负责人、跟进备注),并说明理由。
小测
选一个答案,马上看解析。
Q1计划员早先把 WO-1042 的 status 改成了 paused。现在 MES 把它改成 done。当前值是?
有改动的属性以改动为准,同步冲不掉它。overridden 就是用来提醒「数据源已经是另一个值」的。
Q2mirror 模式下,某个工单不再出现在 MES 的数据流里,会怎样?
行消失只是「源头消失」,不是删除;对象和人的改动都保留,行回来时对象跟着回来。
Q3两个计划员同时打开 WO-1042 准备修改。怎样防止后保存的悄悄覆盖先保存的?
MES 是只读的,Semantic 不会去锁它;并发控制靠 rev:谁的 ifRev 落后,谁就被拒绝,刷新后再改。