3. Windchill核心数据模型

Windchill 二次开发中,最容易“写得出代码、却查不到数据”的根因,往往不是 API 不熟,而是对底层数据模型理解不深。Windchill 并不是把产品、部件、图纸、BOM 平铺在若干张表里,而是用一套“对象 + 关系 + 版本 + 生命周期”的模型把它们组织起来。理解这套模型,才能知道 WTPart、WTDocument、EPMDocument、WTChangeOrder2 这些对象在数据库里究竟以什么形态存在,以及为什么某些查询必须走导航接口而不是直接拼 SQL。

一、六类核心对象各自“是什么”

产品(Product / Container)在 Windchill 中通常体现为 WTProduct 或产品容器(Product Container),它是数据组织的顶层上下文,决定了编号唯一性范围、访问控制策略、生命周期模板和团队角色。产品本身一般不直接挂 BOM,而是作为部件、文档的归属域。

部件(WTPart)是描述“要造什么”的主数据对象,承载物料号、名称、单位、来源(自制/外购)、版本与生命周期状态。部件是 BOM 的节点载体,也是变更影响分析的主要对象。

文档(WTDocument)是通用文档对象,用于承载规范、工艺说明、测试报告等非 CAD 内容,通过 DescribedBy 或 Reference 关系与部件关联。

CAD 文档(EPMDocument)是 CAD 模型在 Windchill 中的表示对象,通常由 Creo、SolidWorks 等通过 Workgroup Manager 检入生成。它保存 CAD 结构、几何引用和与部件的链接关系,是“设计数据”与“制造主数据”之间的桥梁。

BOM(Bill of Materials)在 Windchill 中不是一张独立表,而是由 WTPartUsageLink(部件使用关系)构成的父子结构。每个 UsageLink 记录父件、子件、数量、单位、位号、查找编号等,并支持按视图(Design/Manufacturing)区分。

变更对象(Change Object)包括 ChangeRequest(ECR)、ChangeNotice(ECN)、ChangeOrder2(ECO)等,用于驱动受控对象的版本升级与状态迁移。变更对象通过 AffectedItem、Changeable 等关系挂接受影响对象。

二、对象之间的关系:不是外键,而是“链接对象”

Windchill 的关系建模有一个关键特征:多对多关系通常被建模为独立对象。例如部件与部件之间的 BOM 关系,落地为 WTPartUsageLink 对象;部件与文档之间的描述关系,落地为 DescribedByLink;变更与受影响项之间,落地为 AffectedItem。这些链接对象本身也有版本、生命周期和属性,因此不能简单理解为数据库外键。

下图给出六类核心对象及其主要关系的结构示意,箭头方向表示“从属/引用”方向:

产品 / 产品容器 WTProduct · 编号域 · 生命周期模板 部件 WTPart 物料号 · 版本 · 状态 · 视图 BOM 使用关系 WTPartUsageLink · 数量/位号 CAD 文档 EPMDocument CAD 结构 · 几何引用 文档 WTDocument 规范 · 工艺 · 报告 变更对象 ECR/ECN/ECO AffectedItem · Changeable 归属 父件 子件 EPM 构建链接 DescribedBy 受影响项 受影响项 受影响项 归属/引用 BOM 父子 使用关系 变更影响

三、版本与迭代:Iteration 与 Revision 的区别

Windchill 的版本模型分两层:修订版本(Revision)如 A、B、C,表示设计意图发生受控变更;迭代版本(Iteration)如 A.1、A.2,表示同一修订下的多次检入。每次检入都会生成新的 Iteration,但只有经过变更流程才会升 Revision。开发中常见的错误是:用 getVersionIdentifier() 拿到 A.2 后,误以为它是修订版本。正确做法是分别取 getRevision() 与 getIteration(),或使用 VersionControlHelper.getVersionIdentifier() 组合判断。

版本对象在持久化上分为 VersionedObject(版本主对象)与 IteratedObject(迭代对象)。前者保存跨修订的稳定标识,后者保存某一次具体状态。查询“最新已发布版本”时,通常需要先定位 VersionedObject,再按状态与迭代号筛选。

四、持久化机制:对象、链接与关系表

Windchill 底层使用 Oracle 或 SQL Server,但业务对象并不直接对应单张表。以 WTPart 为例,其数据分散在 WTPart、WTPartMaster、VersionedObject、IteratedObject 等多张表中;BOM 关系则落在 WTPartUsageLink 及其关联表。直接写 SQL 查询不仅容易漏掉版本过滤,还会绕过访问控制与缓存,导致结果与 UI 不一致。

正确的持久化访问路径是:通过 PersistenceHelper 或 QuerySpec 构造查询,由 Windchill 的 ORM 层完成对象装配。例如按编号查部件:

QuerySpec qs = new QuerySpec(WTPart.class);
qs.appendWhere(new SearchCondition(
    WTPart.class, "master>number", SearchCondition.EQUAL, "P-1001"),
    new int[]{0});
QueryResult qr = PersistenceHelper.manager.find(qs);
while (qr.hasMoreElements()) {
    WTPart part = (WTPart) qr.nextElement();
    System.out.println(part.getRevision() + "." + part.getIteration());
}

这段代码的关键点在于 master>number 这种“导航属性”写法:它告诉 ORM 从 WTPart 导航到其 Master 对象再取 number,而不是在 WTPart 表里找 number 字段。这正是对象模型与关系模型之间的映射体现。

五、BOM 的展开与持久化细节

BOM 展开时,Windchill 会沿 WTPartUsageLink 逐层导航。每个 UsageLink 记录 quantity、unit、findNumber、referenceDesignator 等属性,并关联到子件的特定版本。开发中若需要“取某父件下所有子件的最新版本”,不能只查 UsageLink,还要对子件做版本解析,否则可能拿到旧版本。

此外,BOM 支持按视图过滤。Design 视图与 Manufacturing 视图可以有不同的子件集合与数量。持久化时,视图信息记录在 UsageLink 的 view 属性或关联的 View 对象上。查询时必须显式指定视图,否则默认行为可能不符合预期。

六、变更对象如何驱动版本升级

变更对象本身也是版本化对象。一个 ECO 从“拟制”到“已发布”,会经历生命周期状态迁移。当 ECO 进入“已发布”时,其挂接的 AffectedItem 会触发受控对象的修订升级:部件从 A 升到 B,CAD 文档同步升版,BOM 关系被复制到新版本上。这个过程不是简单改字段,而是由 Windchill 的变更框架(Change Framework)通过 Changeable 接口和 AffectedItem 关系自动完成。

二次开发中若要在变更发布后做扩展,通常应挂接 ChangeOrder2 的生命周期监听器,而不是直接修改版本字段。监听器里可以通过 Changeable 拿到受影响对象,再执行自定义逻辑,例如同步 ERP 物料状态或触发下游通知。

实践提示:调试数据模型问题时,优先使用 Windchill 的 wt.query 包构造查询,而不是 JDBC 直连。若必须核对底层表,建议先用 PersistenceHelper.manager.find() 拿到对象,再通过 getPersistInfo() 查看其数据库标识,这样能保证版本、状态、访问控制都被正确应用。

七、小结:模型理解决定开发效率

产品、部件、文档、CAD 文档、BOM、变更对象这六类对象,构成了 Windchill 数据模型的主干。它们之间不是简单的表关联,而是通过链接对象、版本对象和生命周期状态交织成一张有向图。持久化机制则把这套对象模型映射到关系数据库,并通过 ORM 层屏蔽了底层细节。二次开发中,凡是涉及“查不到、查重了、版本不对、BOM 展开异常”的问题,几乎都能回溯到对这张图的理解偏差。把对象关系、版本语义和查询路径这三件事理清,后续的 API 调用、监听器扩展和集成开发都会顺畅得多。