datai/datai-scenes/datai-scene-salesforce/docs/prompts/2026-01-30-004-prompt-查询功能.md

9.8 KiB
Raw Permalink Blame History

提示词:查询功能

引用真源

需求描述

根据需求文档,实现 Salesforce Partner API 的查询功能,包括:

  1. Query:执行 SOQL 查询

    • 支持执行标准 SOQL 查询语句
    • 支持设置批次大小1-2000默认 500
    • 返回查询结果和分页信息
    • 支持关系查询(如 Account.Name
    • 查询最多返回 50000 条记录
    • OFFSET 上限为 2000且必须与 LIMIT 一起使用
  2. QueryAll:查询所有记录(包括已删除的)

    • 与 Query 类似,但返回包括已删除的记录
    • 支持查询回收站中的记录IsDeleted = true
    • 支持设置批次大小
  3. QueryMore:获取查询结果的下一页

    • 使用 queryLocator 获取下一页数据
    • 支持连续分页直到 done 为 true
    • 固定使用 source org 类型
  4. Search:执行 SOSL 搜索

    • 支持全文搜索多个对象
    • 返回搜索结果列表
    • 支持跨对象搜索

设计方案

根据设计文档和决策记录,采用以下技术方案:

  1. 架构设计

    • 分层架构Controller → Service → PartnerConnectionFactory → Salesforce API
    • ControllerRESTful API 接口,处理 HTTP 请求
    • Service业务逻辑层调用 Salesforce API
    • PartnerConnectionFactorydatai-salesforce-auth 模块获取连接
  2. 数据模型

    • 使用 DTO/VO 模式进行数据封装
    • DTOQueryDto、QueryAllDto、QueryMoreDto、SearchDto
    • VOQueryResultVo、SearchResultVo、SearchRecordVo
  3. 查询构建

    • 使用 datai-salesforce-common 模块的 SoqlBuilder 构建类型安全的 SOQL 查询
    • 支持链式调用,提高可读性
  4. 结果处理

    • 将 Salesforce 返回的 SObject[] 完整转换为 List<Map<String, Object>>
    • 递归处理嵌套的 SObject 对象(支持关系查询)
    • 解耦 Salesforce 特定的对象,返回通用 Map 结构
  5. 分页策略

    • 使用 Salesforce 提供的 QueryMore 方法进行服务端分页
    • 使用 QueryLocator 标识查询位置
    • 客户端可选择是否获取所有数据或分页获取
  6. 异常处理

    • 使用 datai-salesforce-common 模块的异常类
    • SalesforceOperationException操作异常
    • SalesforceAuthException认证异常
    • 统一的异常处理和错误码
  7. 固定配置

    • 固定使用 source org 类型ORG_TYPE = "source"
    • 通过 PartnerConnectionFactory.getConnection(ORG_TYPE) 获取连接

输出格式要求

1. 必须包含以下文件

Controller 层

  • PartnerQueryController.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/controller/PartnerQueryController.java
    • 提供 4 个 RESTful API 接口
    • 使用 @RestController@RequestMapping("/partner")
    • 使用 @Validated 进行参数校验
    • 使用 Swagger 注解 @Operation@Schema 生成 API 文档

Service 层

  • IPartnerQueryService.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/service/IPartnerQueryService.java
    • 定义 4 个查询方法
  • PartnerQueryServiceImpl.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/service/impl/PartnerQueryServiceImpl.java
    • 实现查询逻辑
    • 处理 SObject 到 Map 的转换
    • 处理异常

DTO 层

  • QueryDto.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/model/dto/QueryDto.java
  • QueryAllDto.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/model/dto/QueryAllDto.java
  • QueryMoreDto.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/model/dto/QueryMoreDto.java
  • SearchDto.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/model/dto/SearchDto.java

VO 层

  • QueryResultVo.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/model/vo/QueryResultVo.java
  • SearchResultVo.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/model/vo/SearchResultVo.java
  • SearchRecordVo.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/model/vo/SearchRecordVo.java

工具类

  • 复用现有的 SObjectConverter.java(路径:datai-salesforce-partner/src/main/java/com/datai/partner/util/SObjectConverter.java

2. 必须包含单元测试

  • PartnerQueryServiceImplTest.java(路径:datai-salesforce-partner/src/test/java/com/datai/partner/service/impl/PartnerQueryServiceImplTest.java
    • 测试 Query 方法
    • 测试 QueryAll 方法
    • 测试 QueryMore 方法
    • 测试 Search 方法
    • 测试异常场景

3. 代码结构要求

  • 使用 Lombok 简化代码(@Data、@NoArgsConstructor、@AllArgsConstructor、@Builder
  • 使用 Spring 的依赖注入(@Autowired
  • 使用 JSR-380 进行参数校验(@NotBlank、@Min、@Max
  • 使用 Swagger/OpenAPI 3 注解生成 API 文档

4. 复用已有组件

  • 复用 PartnerConnectionFactory(从 datai-salesforce-auth 模块)
  • 复用 SObjectConverter(已存在于 datai-salesforce-partner 模块)
  • 复用 datai-salesforce-common 模块的异常类
  • 复用 datai-salesforce-common 模块的 SoqlBuilder

代码规范要求

1. 命名规范

  • 类命名:首字母大写,驼峰命名,如 PartnerQueryController
  • 方法命名:首字母小写,驼峰命名,如 query
  • 变量命名:首字母小写,驼峰命名,如 queryResult
  • 常量命名:全大写,下划线分隔,如 ORG_TYPE

2. 注释规范

  • 类注释:使用 /** */,包含类功能描述、作者、创建时间
  • 方法注释:使用 /** */,包含方法功能、参数、返回值、异常描述
  • 字段注释:使用 /** */,包含字段功能描述
  • Swagger 注解:使用 @Operation 描述接口,使用 @Schema 描述字段

3. 代码格式

  • 使用 4 个空格缩进
  • 行宽不超过 120 字符
  • 使用 import 静态导入,避免通配符导入

4. 异常处理

  • 使用 try-finally 确保连接释放
  • 捕获 ConnectionException 和 ApiFault 并转换为业务异常
  • 提供清晰的错误信息

5. 日志规范

  • 使用 SLF4J 记录日志
  • 记录关键操作和异常信息
  • 不记录敏感信息(如密码)

测试要求

1. 测试覆盖率

  • 单元测试覆盖率不低于 80%

2. 测试场景

  • Query 方法

    • 正常查询成功
    • 带批次大小的查询
    • 关系查询Account.Name
    • 空结果查询
    • 无效 SOQL 语法
    • 网络异常
  • QueryAll 方法

    • 正常查询所有记录(包括已删除的)
    • 查询回收站记录
    • 带批次大小的查询
    • 空结果查询
    • 无效 SOQL 语法
  • QueryMore 方法

    • 正常获取下一页
    • 连续分页直到 done 为 true
    • 无效的 queryLocator
    • 查询已完成的 locator
  • Search 方法

    • 正常搜索成功
    • 跨对象搜索
    • 空结果搜索
    • 无效 SOSL 语法
    • 网络异常
  • 异常场景

    • 连接获取失败
    • 连接释放失败
    • API 调用超时
    • 认证失败

3. 测试框架

  • 使用 JUnit 5 进行单元测试
  • 使用 Mockito 进行依赖模拟
  • 使用 AssertJ 进行断言

4. 测试用例命名

  • 测试用例命名规范:test+方法名+场景,如 testQuerySuccess
  • 测试类命名规范:被测类名+Test,如 PartnerQueryServiceImplTest

5. 测试数据

  • 使用 Mockito 模拟 PartnerConnectionFactory
  • 使用 Mockito 模拟 PartnerConnection
  • 使用 Mockito 模拟 QueryResult 和 SearchResult
  • 使用真实 SObject 对象或模拟对象

注意事项

1. SOQL 语法限制

  • 不支持 SELECT *,必须指定具体字段
  • 不支持 BETWEEN 操作符,使用 >=<= 替代
  • 不支持 JOIN 操作,使用关系查询(如 Account.Name)替代
  • 不支持 UNION 操作
  • OFFSET 上限为 2000且必须与 LIMIT 一起使用
  • 查询最多返回 50000 条记录

2. 性能考虑

  • 合理设置批次大小(默认 500最大 2000
  • 对于大数据量查询,使用 QueryMore 分页获取
  • 避免在循环中频繁创建连接
  • 及时释放连接资源

3. 安全性

  • 固定使用 source org 类型,不暴露 orgType 参数
  • 不记录敏感信息(如查询语句中的敏感数据)
  • 验证 SOQL/SOSL 语法,防止注入攻击
  • 使用若依的权限控制注解(如需要)

4. 兼容性

  • 与已实现的 CRUD 操作和批量操作保持代码风格一致
  • 复用现有的 SObjectConverter 工具类
  • 复用现有的异常处理机制
  • 复用现有的 PartnerConnectionFactory

5. 文档要求

  • 所有公共方法必须有完整的 JavaDoc 注释
  • 所有 REST API 接口必须有 Swagger 注解
  • 所有 DTO/VO 字段必须有 @Schema 注解
  • 提供清晰的错误码和错误信息

示例代码参考

Query 示例

// 使用 SoqlBuilder 构建查询
String soql = new SoqlBuilder()
    .select("Id", "Name", "Industry")
    .from("Account")
    .whereEq("Status", "Active")
    .orderBy("Name", SortOrder.ASC)
    .limit(100)
    .build();

// 执行查询
QueryResultVo result = partnerQueryService.query(soql, 500);

QueryMore 示例

// 首次查询
QueryResultVo firstResult = partnerQueryService.query(soql, 500);

// 获取下一页
if (!firstResult.getDone()) {
    QueryResultVo nextResult = partnerQueryService.queryMore(firstResult.getQueryLocator());
}

Search 示例

// 执行搜索
String sosl = "FIND {Acme} IN ALL FIELDS RETURNING Account(Id, Name), Contact(Id, Name)";
SearchResultVo result = partnerQueryService.search(sosl);