CRUD / Query 开发主路径
按能力组合创建、更新、查询和扩展条件,保持生命周期一致。
浏览全部手册
本页目录
文档来源与 Markdown 原文
权威正文:ineed-core/docs/project-development/crud-query-guide.md。网站按工作区快照同步,原文中的历史日期和验证范围保留。
开始编码前核对同版本源码;跨仓文件引用可在源码定位目录查找。
下载 Markdown 原文 ↓适用范围
本文档覆盖 Ineed-Core 当前两条开发主链路:
- 阻塞式:
WebMvc + JPA/JDBC/MyBatis-Flex - 响应式:
WebFlux + R2DBC
阻塞式链路是当前优先推荐的验收基线;响应式链路作为对等能力线同步维护。新业务模块、公共能力或代码生成任务,如果需求没有明确限定单线实现,应同时评估并对齐两条线。
标准主路径
两条链路共享同一分层架构:
Controller -> Service -> Manager -> Repository/EntityManager
| 层次 | 阻塞式模块 | 响应式模块 | 职责 |
|---|---|---|---|
| Web 入口 | ineed-core-webmvc |
ineed-core-webflux |
对外暴露 API、参数校验、统一返回 |
| 业务编排 | ineed-core-engine |
ineed-core-engine-reactive |
事务边界、业务编排、桥接 Manager |
| 业务能力 | ineed-core-engine |
ineed-core-engine-reactive |
单类实体规则、CRUD、查询、状态切换 |
| 数据访问 | ineed-core-data-jpa/jdbc/mybatis-flex |
ineed-core-data-r2dbc |
持久化与查询执行 |
标准能力入口总览
以下能力按需组合,只有业务对象具备对应能力时才实现对应接口。
| 能力 | WebMvc Controller | WebFlux Controller | Service | Manager | 说明 |
|---|---|---|---|---|---|
| 创建 | ICreateController |
ICreateController |
ICreateService |
ICreateManager |
单条与批量创建 |
| 更新 | IUpdateController |
IUpdateController |
IUpdateService |
IUpdateManager |
按 AO.id 更新 |
| 按 ID 查询 | IFindByIdController |
IFindByIdController |
IFindByIdService |
IFindByIdManager |
单 ID 与批量 ID 查询 |
| 分页查询 | ISearchController |
ISearchController |
ISearchService |
ISearchManager |
标准 CommonParameters + Query |
| 回收站查询 | ISearchRecycleController |
ISearchRecycleController |
ISearchRecycleService |
ISearchRecycleManager |
查询已逻辑删除数据 |
| 逻辑删除与恢复 | ILogicDeleteController |
ILogicDeleteController |
ILogicDeleteService |
ILogicDeleteManager |
单/批量逻辑删除、恢复 |
| 物理删除 | IPhysicsDeleteController |
IPhysicsDeleteController |
IPhysicsDeleteService |
IPhysicsDeleteManager |
单/批量物理删除;forceDelete 无标准 Web 入口 |
| 字典查询 | ISearchDictionaryController |
ISearchDictionaryController |
ISearchDictionaryService |
ISearchDictionaryManager |
返回 DictionaryValue |
| 树查询 | ISearchTreeController |
同左 | ISearchTreeService |
ISearchManager |
返回树节点,query.lazyLoad=true 时按父节点懒加载 |
| 树字典查询 | ISearchDictionaryTreeController |
同左 | ISearchDictionaryTreeService |
ISearchManager |
返回字典树 |
| 按主对象查询 | ISearchOfMasterIdController |
同左 | ISearchOfMasterIdService |
IFindByIdManager + ISearchManager |
先查主对象再查关联列表 |
| 按主对象字典查询 | ISearchDictionaryOfMasterIdController |
同左 | ISearchDictionaryOfMasterIdService |
IFindByIdManager + ISearchDictionaryManager |
主对象关联字典查询 |
| 按主对象字典树查询 | ISearchDictionaryTreeOfMasterIdController |
同左 | ISearchDictionaryTreeOfMasterIdService |
IFindByIdManager + ISearchManager |
主对象关联字典树查询 |
| 数据状态 | IEnableController / ILockController / IPublishController / IDefaultController / IPrimaryController |
同左 | 对应 *Service |
对应 *Manager |
单/批量状态切换 |
| 排序 | IOrderController |
IOrderController |
IOrderService |
IOrderManager |
moveBefore/After/Top/Bottom |
| 重复校验 | IDuplicateController |
IDuplicateController |
IDuplicateService |
IDuplicateManager |
创建/更新场景重复检查 |
| 账户动作 | IAccountController |
IAccountController |
IAccountService |
IAccountManager |
重置密码、启用、禁用、锁定、解锁 |
CRUD 入口矩阵
所有路径相对于业务 Controller 根路径。权限后缀两条线一致。
| 能力 | HTTP | 路径 | 权限后缀 | WebMvc 返回 | WebFlux 返回 |
|---|---|---|---|---|---|
| 单条创建 | POST |
根路径 | create |
ResponseResults<V> |
Mono<ResponseResults<V>> |
| 批量创建 | POST |
/batch |
batch-create |
ResponseResults<Iterable<V>> |
Mono<ResponseResults<Iterable<V>>> |
| 更新 | PUT |
根路径 | update |
ResponseResults<V> |
Mono<ResponseResults<V>> |
| 逻辑删除 | DELETE |
/{id} |
logic-delete |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量逻辑删除 | DELETE |
/batch/logic-delete |
batch-logic-delete |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 恢复 | PUT |
/recovery/{id} |
recovery |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量恢复 | PUT |
/recovery |
batch-recovery |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 物理删除 | DELETE |
/physics/{id} |
physics-delete |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量物理删除 | DELETE |
/batch/physics-delete |
batch-physics-delete |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
forceDelete(id / idSet) 只存在于 IPhysicsDeleteService / IPhysicsDeleteManager,标准 Controller 未暴露入口。业务如需开放强制删除,必须显式定义自定义接口和权限点。
查询入口矩阵
| 能力 | HTTP | 路径 | WebMvc 返回 | WebFlux 返回 |
|---|---|---|---|---|
| 分页查询 | GET |
根路径 | ResponseResults<QueryResults<V>> |
Mono<ResponseResults<QueryResults<V>>> |
| 按 ID 查询 | GET |
/{id} |
ResponseResults<V> |
Mono<ResponseResults<V>> |
| 批量按 ID 查询 | GET |
/batch?idSet=... |
ResponseResults<Iterable<V>> |
Mono<ResponseResults<Iterable<V>>> |
| 回收站查询 | GET |
/recycle |
ResponseResults<QueryResults<V>> |
Mono<ResponseResults<QueryResults<V>>> |
| 字典查询 | GET |
/dictionary |
ResponseResults<QueryResults<DictionaryValue>> |
Mono<ResponseResults<QueryResults<DictionaryValue>>> |
| 树查询 | GET |
/tree |
ResponseResults<QueryResults<TN>> |
Mono<ResponseResults<QueryResults<TN>>> |
| 树字典查询 | GET |
/tree/dictionary |
ResponseResults<QueryResults<DictionaryValueTreeNode>> |
Mono<ResponseResults<QueryResults<DictionaryValueTreeNode>>> |
| 按主对象查询 | GET |
/of/{masterId} |
ResponseResults<MasterQueryResults<M, V>> |
Mono<ResponseResults<MasterQueryResults<M, V>>> |
| 按主对象字典查询 | GET |
/dictionary/of/{masterId} |
ResponseResults<QueryResults<DictionaryValue>> |
Mono<ResponseResults<QueryResults<DictionaryValue>>> |
| 按主对象字典树查询 | GET |
/tree/dictionary/of/{masterId} |
ResponseResults<MasterQueryResults<M, DictionaryValueTreeNode>> |
Mono<ResponseResults<MasterQueryResults<M, DictionaryValueTreeNode>>> |
查询类标准 Controller 默认方法没有接口级 @PreAuthorize。如果业务模块要在权限清单中登记查询 API 权限,应按 frontend-integration-guide.md 生成 api 节点。
数据状态、排序、重复和账户入口矩阵
| 能力 | HTTP | 路径 | 权限后缀 | WebMvc 返回 | WebFlux 返回 |
|---|---|---|---|---|---|
| 启用 | PUT |
/enable/{id} |
enable |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量启用 | PUT |
/enable |
batch-enable |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 禁用 | PUT |
/disable/{id} |
disable |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量禁用 | PUT |
/disable |
batch-disable |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 锁定 | PUT |
/lock/{id} |
lock |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量锁定 | PUT |
/lock |
batch-lock |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 解锁 | PUT |
/unlock/{id} |
unlock |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量解锁 | PUT |
/unlock |
batch-unlock |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 发布 | PUT |
/publish/{id} |
publish |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量发布 | PUT |
/publish |
batch-publish |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 撤销发布 | PUT |
/withdraw/{id} |
withdraw |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量撤销发布 | PUT |
/withdraw |
batch-withdraw |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 设为默认 | PUT |
/default/{id} |
default |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量设为默认 | PUT |
/default |
batch-default |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 取消默认 | PUT |
/non-default/{id} |
non-default |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量取消默认 | PUT |
/non-default |
batch-non-default |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 设为主要 | PUT |
/primary/{id} |
primary |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量设为主要 | PUT |
/primary |
batch-primary |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 取消主要 | PUT |
/non-primary/{id} |
non-primary |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 批量取消主要 | PUT |
/non-primary |
batch-non-primary |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 移到目标前 | PUT |
/order/before |
order |
ResponseResults<V> |
Mono<ResponseResults<V>> |
| 移到目标后 | PUT |
/order/after |
order |
ResponseResults<V> |
Mono<ResponseResults<V>> |
| 移到顶部 | PUT |
/order/top |
order |
ResponseResults<V> |
Mono<ResponseResults<V>> |
| 移到底部 | PUT |
/order/bottom |
order |
ResponseResults<V> |
Mono<ResponseResults<V>> |
| 创建重复校验 | POST |
/duplicate |
duplicate |
ResponseResults<Boolean> |
Mono<ResponseResults<Boolean>> |
| 更新重复校验 | PUT |
/duplicate |
duplicate |
ResponseResults<Boolean> |
Mono<ResponseResults<Boolean>> |
| 重置账户密码 | PUT |
/account/passwd/reset/{id} |
account-passwd-reset |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 禁用账户 | PUT |
/account/disable/{id} |
account-disable |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 启用账户 | PUT |
/account/enable/{id} |
account-enable |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 锁定账户 | PUT |
/account/lock/{id} |
account-lock |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
| 解锁账户 | PUT |
/account/unlock/{id} |
account-unlock |
ResponseResults<Void> |
Mono<ResponseResults<Void>> |
数据状态能力由实体 DataStatusFeature 决定,不应默认全开。实体没有对应能力时不生成对应 Controller / Service / Manager。
CRUD 接入步骤
1. 定义 Web 层入口
阻塞式入口位于 ineed-core-webmvc,响应式入口位于 ineed-core-webflux,围绕以下接口展开:
ICreateController/IUpdateController/ILogicDeleteController/IPhysicsDeleteController
2. 定义 Service 层桥接
ICreateService/IUpdateService/ILogicDeleteService/IPhysicsDeleteService
通过 getManager() 暴露 Manager,通过 ServiceSupport.requireManager(...) 调用具体能力。
3. 定义 Manager 层能力
ICreateManager/IUpdateManager/ILogicDeleteManager/IPhysicsDeleteManager
具体数据栈实现在对应 JPA/JDBC/MyBatis-Flex/R2DBC 模块中完成。
4. 删除能力语义
- 逻辑删除使用
ILogicDelete*系列接口 - 恢复已删除数据由
recovery(...)暴露 - 物理删除使用
IPhysicsDelete*系列接口 - 删除前保护、删除后清理和恢复补偿规则见 delete-hook-and-logging-guide.md
查询接入步骤
1. 定义查询 Web 入口
列表查询入口是 ISearchController,接收 CommonParameters 与业务 Query 组装为 QueryParameters。
按 ID 查询入口是 IFindByIdController,支持 GET /{id}(单条)和 GET /batch?idSet=...(批量)。
2. 定义查询 Service / Manager
列表查询:ISearchService → ISearchManager,返回 QueryResults。
按 ID 查询:IFindByIdService → IFindByIdManager。
3. 统一参数与返回模型
QueryParameters统一承载searchKey、current、pageSize、sorterList、queryObjectAbstractVO作为标准返回对象基类ResponseResults<T>作为统一响应外壳
4. 扩展查询入口
| 查询能力 | 路径常量 | 返回模型 |
|---|---|---|
| 回收站查询 | Urls.SEARCH_RECYCLE |
QueryResults<V> |
| 字典查询 | Urls.SEARCH_DICTIONARY |
QueryResults<DictionaryValue> |
| 树查询 | Urls.SEARCH_TREE |
QueryResults<TN> |
| 树字典查询 | Urls.SEARCH_TREE_DICTIONARY |
QueryResults<DictionaryValueTreeNode> |
| 按主对象查询 | Urls.SEARCH_OF_MASTER_ID |
MasterQueryResults<M, V> |
| 按主对象字典查询 | Urls.SEARCH_DICTIONARY_OF_MASTER_ID |
QueryResults<DictionaryValue> |
| 按主对象字典树查询 | Urls.SEARCH_DICTIONARY_TREE_OF_MASTER_ID |
MasterQueryResults<M, DictionaryValueTreeNode> |
SearchOfMasterId 是主从/关联场景:先用 IFindByIdManager 查主对象,再用 ISearchManager 查询关联列表。
动态注册约定
ineed-core-webmvc 扫描 IWebMvcApi Bean,ineed-core-webflux 扫描 IWebFluxApi Bean,把标准接口默认方法注册到路由中。
业务控制器通常只需要:
- 实现对应
I*Controller接口 - 提供
getResourceKey()和getResourceName() - 不需要为每个默认方法重复手写转发
getResourceKey() 和 getResourceName() 优先返回模块常量中的 XxxConstant.Resource.KEY_* / XxxConstant.Resource.NAME_*。
getResourceName() 返回业务展示名,OpenAPI 公共接口摘要会用它将 资源 占位替换为具体业务名称。
响应式实现约束
WebFlux 实现必须避免将响应式链路退化成装配期同步执行:
- 自定义 WebFlux Controller 方法统一返回
Mono.defer(() -> { ... }),把入口日志、上下文读取、参数准备和结果封装都放进订阅期 - Controller 中包装 Service 返回值时优先使用
ResultBuild.success(serviceMono);不要在链外先执行日志或同步逻辑后再用serviceMono.flatMap(ResultBuild::success)拼接 - Controller 参数校验通过
Mono.defer(...)和ValidationExceptionSupport.validate(...)延迟到订阅期 - 无返回体动作型接口统一返回
Mono<ResponseResults<Void>>,使用.then(ResultBuild.success()) - 集合结果返回
Mono<ResponseResults<Iterable<T>>>,不生成Mono<ResponseResults<Flux<T>>> Flux只保留在 Service / Manager 内部或真正的流式接口中- R2DBC manager / repository 中不使用
Mono.just(getEntityClass())等装配期求值写法,使用Mono.defer(...)或getEntityClassMono()
WebMvc 与 WebFlux 对齐要求
同一业务对象如果同时暴露两条线,必须保持一致:
- URL 路径一致
- 权限资源后缀一致
- 参数名一致(
common、query、idSet) getResourceKey()/getResourceName()语义一致- 返回
ResponseResults/QueryResults/MasterQueryResults结构一致 - 标准能力组合一致,除非需求明确排除
非业务对象级内置入口
ineed-core-webmvc 和 ineed-core-webflux 还包含健康检查、i18n 语言列表和应用模块元数据等内置 Controller。这些属于框架运行支撑,生成业务模块时不要为每个业务对象复制。
运行与验证
阻塞式主链路验证:
mvn -pl ineed-core-tests/ineed-core-test-webmvc -am \
-Dtest=WebMvcJpaBusinessChainTest,WebMvcJdbcBusinessChainTest,WebMvcMybatisFlexBusinessChainTest,\
WebMvcJpaSearchBusinessChainTest,WebMvcJdbcSearchBusinessChainTest,WebMvcMybatisFlexSearchBusinessChainTest \
-Dsurefire.failIfNoSpecifiedTests=false test
响应式主链路验证:
mvn -pl ineed-core-reactive-modules/ineed-core-webflux,ineed-core-tests/ineed-core-test-webflux -am test
当前不覆盖
- 项目开发契约 → development-contract.md
- 自定义业务约定细则 → custom-business-layering-guide.md
- 删除钩子与日志追踪 → delete-hook-and-logging-guide.md
- 前端联调 → frontend-integration-guide.md
最后更新:2026-05-15
仍有疑问?按反馈清单整理复现信息 →