<!-- generated-by: gsd-doc-writer -->
# 业务对象与能力组合

## 对象如何分工

| 对象 | 作用 | 开发时的决定 |
| --- | --- | --- |
| AO | 创建、编辑或动作入参 | 可写字段、必填校验、禁止客户端控制的字段 |
| Query | 业务查询条件 | 哪些条件可查询、如何映射到数据栈查询表达式 |
| VO | 面向调用方的返回数据 | 展示字段、关联结果、敏感字段隐藏 |
| DTO | 跨模块传递的共享数据 | 稳定语义和依赖边界，不绑定某 ORM |
| Entity | 某数据栈的持久化实体 | 表映射、租户模式、状态能力和持久化类型 |
| Converter | AO/Entity/VO 转换 | 复用父接口，特殊映射才覆盖方法 |

新业务 contract 放在 `contract/ao`、`contract/query`、`contract/vo`、`contract/dto`；转换实现放 `converter/`。MyBatis-Flex 的 `mapper/` 专用于持久化接口。

字段从 SQL → Entity → AO/VO/Query 不一定一对一暴露。例如审计字段由框架维护，秘密字段不能原样返回，关联名称可以是查询投影。为每个字段明确读写权限和转换来源。

## 选择基类与能力

先判断实体需要租户、树、逻辑删除、排序、数据状态或所有者能力，再选择对应数据栈基类。不要为得到一个字段顺带开放所有动作。

`@EnableDataStatus` 声明数据状态能力；基础实体默认提供的能力与最终实体打开的能力见[数据状态指南](../guides/data-status.md)。能力接口、Controller 暴露动作、权限清单与前端按钮必须保持一致。

一个对象是否“可以删除”和是否“有物理删除接口”是两回事。生命周期拦截仍会检查实体状态、租户和业务引用。

## 以一个新增字段为例

新增条目说明字段时，按以下顺序检查：SQL 列与默认值 → 各目标数据栈 Entity → 可写 AO 与校验 → Converter → VO → OpenAPI/i18n → 测试。如果还需要按说明搜索，再改 Query、各栈查询实现和查询测试。

不要只看编译通过：补一个创建后查询的断言，才能发现转换遗漏；补旧记录读取场景，才能发现默认值或兼容问题。

源码参考：[AbstractAO](../../ineed-core-base/src/main/java/com/ineed/base/contract/ao/AbstractAO.java)、[AbstractBaseQuery](../../ineed-core-base/src/main/java/com/ineed/base/contract/query/AbstractBaseQuery.java)、[IEntity](../../ineed-core-data-base/src/main/java/com/ineed/core/data/entity/IEntity.java)。完整生成输入见[需求模板](../project-development/module-requirements-template.md)。
