32 KiB
datai-salesforce-common 模块详细文档
模块概述
基本信息
- 模块名称: datai-salesforce-common
- 模块类型: 通用工具模块
- 版本: 1.0.0
- Java 版本: 22
- 编码: UTF-8
功能描述
datai-salesforce-common 模块是 Salesforce 集成体系的通用工具模块,提供常量定义、工具类、数据转换、异常处理等基础功能。该模块被其他所有 Salesforce 相关模块依赖,是整个体系的基础设施层。
核心特性
- 常量管理:统一的 Salesforce 相关常量定义
- SOQL 构建:强大的 SOQL 查询构建器
- 数据转换:Salesforce 数据类型转换工具
- 异常处理:完善的异常体系
- 参数封装:统一的参数封装类
- 工具方法:丰富的工具方法集合
模块架构
整体架构图
┌─────────────────────────────────────────────────────────────────┐
│ datai-salesforce-common │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 常量层(Constants) │ │
│ │ SalesforceConstants | ConfigConstants | Connection │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 工具层(Utils) │ │
│ │ SoqlBuilder | SoqlUtil | ApiListUtils | FileValidation│ │
│ │ IdUtils | ValidationUtils | BooleanConverter │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 转换层(Converters) │ │
│ │ SalesforceDataTypeConverter │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 参数层(Params) │ │
│ │ SalesforceParam | SalesforceStockParam │ │
│ │ SalesforceIncrementParam │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 异常层(Exceptions) │ │
│ │ SalesforceAuthException | SalesforceLoginException │ │
│ │ SalesforceOAuthException | FileUploadException │ │
│ │ ... (30+ 异常类) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 枚举层(Enums) │ │
│ │ FileObjectType │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
分层说明
1. 常量层
负责统一管理 Salesforce 相关常量,包括 API 版本、连接端点、HTTP 方法、日期格式等。
2. 工具层
提供各种工具方法,包括 SOQL 查询构建、文件验证、ID 处理、数据验证等。
3. 转换层
负责数据类型转换,特别是 Salesforce 特有的数据类型转换。
4. 参数层
封装各种业务参数,提供统一的参数传递方式。
5. 异常层
定义完善的异常体系,覆盖各种业务场景。
6. 枚举层
定义业务枚举,提供类型安全的常量定义。
核心组件详解
1. SalesforceConstants(常量类)
类路径: com.datai.common.constant.SalesforceConstants
功能描述: 统一管理 Salesforce 相关常量,按照功能模块分类,便于维护和使用。
主要常量分类:
API 版本常量
// REST API 版本
public static final String REST_API_VERSION = "v59.0";
// Bulk API v1 版本
public static final String BULK_V1_API_VERSION = "47.0";
// Bulk API v2 版本
public static final String BULK_V2_API_VERSION = "v59.0";
连接端点常量
// REST API 端点后缀
public static final String REST_ENDPOINT_SUFFIX = "/services/data/";
// Bulk API v1 端点后缀
public static final String BULK_V1_ENDPOINT_SUFFIX = "/services/async/";
// Bulk API v2 端点后缀
public static final String BULK_V2_ENDPOINT_SUFFIX = "/services/data/v59.0/jobs/";
// SOAP API 端点后缀
public static final String SOAP_ENDPOINT_SUFFIX = "/services/Soap/u/59.0/";
连接类型常量
// 连接类型 - SOAP
public static final String CONNECTION_TYPE_SOAP = "SOAP";
// 连接类型 - REST
public static final String CONNECTION_TYPE_REST = "REST";
// 连接类型 - Bulk API v1
public static final String CONNECTION_TYPE_BULK_V1 = "BULK_V1";
// 连接类型 - Bulk API v2
public static final String CONNECTION_TYPE_BULK_V2 = "BULK_V2";
HTTP 相关常量
// HTTP 方法
public static final String HTTP_METHOD_GET = "GET";
public static final String HTTP_METHOD_POST = "POST";
public static final String HTTP_METHOD_PUT = "PUT";
public static final String HTTP_METHOD_PATCH = "PATCH";
public static final String HTTP_METHOD_DELETE = "DELETE";
// 内容类型
public static final String CONTENT_TYPE_JSON = "application/json";
public static final String CONTENT_TYPE_CSV = "text/csv";
public static final String CONTENT_TYPE_XML = "application/xml";
// 授权头
public static final String AUTH_HEADER_NAME = "Authorization";
public static final String AUTH_HEADER_PREFIX = "Bearer ";
日期格式常量
// Salesforce 日期时间格式
public static final String SF_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
// Salesforce 日期格式
public static final String SF_DATE_ONLY_FORMAT = "yyyy-MM-dd";
// Salesforce 时间格式
public static final String SF_TIME_FORMAT = "HH:mm:ss.SSS'Z'";
批次处理常量
// 大批次大小(外层批次)
public static final int LARGE_BATCH_SIZE = 10000;
// 小批次大小(API 调用批次)
public static final int SMALL_BATCH_SIZE = 200;
// 批次间休眠时间(毫秒)
public static final long BATCH_SLEEP_MS = 1L;
// 日志输出间隔
public static final int LOG_OUTPUT_INTERVAL = 10;
重试相关常量
// 最大重试次数
public static final int MAX_RETRY_COUNT = 3;
// 重试延迟时间(毫秒)
public static final long RETRY_DELAY_MS = 1000L;
2. SoqlBuilder(SOQL 查询构建器)
类路径: com.datai.common.utils.SoqlBuilder
功能描述: 强大的 SOQL 查询构建器,支持复杂查询条件,采用链式调用方式,提供类型安全的查询构建。
SOQL 语法限制:
- 不支持 SELECT *,必须明确指定字段或使用 FIELDS()
- 不支持 BETWEEN 运算符,请使用 >= 和 <= 组合代替
- 不支持 JOIN,使用关系查询(Relationship Queries)如 Account.Name
- 不支持 UNION,无法合并两个不相关的结果集
- 查询最多返回 50000 条记录
- OFFSET 上限为 2000,且必须与 LIMIT 一起使用
- 支持的运算符:=, !=, >, >=, <, <=, LIKE, IN, NOT IN, = NULL, != NULL
- 支持的子句:WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET
核心方法:
SELECT 子句
// 设置 SELECT 子句
public SoqlBuilder select(String... fields)
// 示例
SoqlBuilder builder = new SoqlBuilder()
.select("Id", "Name", "Account.Name", "CreatedDate");
FROM 子句
// 设置 FROM 子句
public SoqlBuilder from(String object)
// 示例
SoqlBuilder builder = new SoqlBuilder()
.from("Contact");
WHERE 子句
// 添加 WHERE 子句
public SoqlBuilder where(String clause)
// 添加等于条件
public SoqlBuilder whereEq(String field, Object value)
// 添加不等于条件
public SoqlBuilder whereNe(String field, Object value)
// 添加大于条件
public SoqlBuilder whereGt(String field, Object value)
// 添加大于等于条件
public SoqlBuilder whereGe(String field, Object value)
// 添加小于条件
public SoqlBuilder whereLt(String field, Object value)
// 添加小于等于条件
public SoqlBuilder whereLe(String field, Object value)
// 添加 IN 条件
public SoqlBuilder whereIn(String field, List<Object> values)
// 添加 NOT IN 条件
public SoqlBuilder whereNotIn(String field, List<Object> values)
// 添加 LIKE 条件
public SoqlBuilder whereLike(String field, String value)
// 添加 NOT LIKE 条件
public SoqlBuilder whereNotLike(String field, String value)
// 添加 = NULL 条件
public SoqlBuilder whereIsNull(String field)
// 添加 != NULL 条件
public SoqlBuilder whereIsNotNull(String field)
// 示例
SoqlBuilder builder = new SoqlBuilder()
.whereEq("Status", "Active")
.whereGt("Amount", 1000)
.whereIn("Type", Arrays.asList("Customer", "Partner"))
.whereLike("Name", "John%");
ORDER BY 子句
// 添加 ORDER BY 子句
public SoqlBuilder orderBy(String field, SortOrder direction)
// 示例
SoqlBuilder builder = new SoqlBuilder()
.orderBy("CreatedDate", SortOrder.DESC)
.orderBy("Name", SortOrder.ASC);
GROUP BY 子句
// 添加 GROUP BY 子句
public SoqlBuilder groupBy(String... fields)
// 示例
SoqlBuilder builder = new SoqlBuilder()
.groupBy("Account.Name", "Status");
HAVING 子句
// 添加 HAVING 子句
public SoqlBuilder having(String clause)
// 示例
SoqlBuilder builder = new SoqlBuilder()
.having("COUNT(Id) > 10");
LIMIT 和 OFFSET 子句
// 设置 LIMIT 子句
public SoqlBuilder limit(int limit)
// 设置 OFFSET 子句
public SoqlBuilder offset(int offset)
// 示例
SoqlBuilder builder = new SoqlBuilder()
.limit(100)
.offset(50);
构建查询
// 构建 SOQL 查询语句
public String build()
// 构建 COUNT 查询语句
public String buildCountQuery()
// 示例
String soql = new SoqlBuilder()
.select("Id", "Name", "Account.Name", "CreatedDate")
.from("Contact")
.whereEq("Status", "Active")
.whereGt("Amount", 1000)
.orderBy("CreatedDate", SortOrder.DESC)
.limit(100)
.build();
完整示例:
// 简单查询
String soql1 = new SoqlBuilder()
.select("Id", "Name")
.from("Account")
.whereEq("Status", "Active")
.orderBy("Name", SortOrder.ASC)
.limit(10)
.build();
// 生成: SELECT Id, Name FROM Account WHERE Status = 'Active' ORDER BY Name ASC LIMIT 10
// 复杂查询
String soql2 = new SoqlBuilder()
.select("Id", "Name", "Account.Name", "TotalAmount", "CreatedDate")
.from("Opportunity")
.whereEq("StageName", "Closed Won")
.whereGe("CloseDate", "2024-01-01")
.whereIn("Type", Arrays.asList("New Customer", "Existing Customer"))
.orderBy("TotalAmount", SortOrder.DESC)
.limit(50)
.build();
// 生成: SELECT Id, Name, Account.Name, TotalAmount, CreatedDate
// FROM Opportunity
// WHERE StageName = 'Closed Won'
// AND CloseDate >= '2024-01-01'
// AND Type IN ('New Customer', 'Existing Customer')
// ORDER BY TotalAmount DESC
// LIMIT 50
// COUNT 查询
String countSoql = new SoqlBuilder()
.select("Id", "Name")
.from("Account")
.whereEq("Status", "Active")
.buildCountQuery();
// 生成: SELECT count(Id) FROM Account WHERE Status = 'Active'
3. SalesforceDataTypeConverter(数据类型转换器)
类路径: com.datai.common.converter.SalesforceDataTypeConverter
功能描述: Salesforce 特定数据类型转换工具,处理日期时间转换、ID 格式转换等。
核心方法:
日期时间转换
// 将 Salesforce 日期时间字符串转换为 Date 对象
public Date convertToDate(String dateTimeString)
// 将 Date 对象转换为 Salesforce 日期时间字符串
public String convertToString(Date date)
// 将 Date 对象转换为 Salesforce 日期字符串
public String convertToDateString(Date date)
// 示例
SalesforceDataTypeConverter converter = new SalesforceDataTypeConverter();
// 转换为 Date
Date date = converter.convertToDate("2024-01-15T10:30:00.000Z");
// 转换为字符串
String dateTimeStr = converter.convertToString(new Date());
String dateStr = converter.convertToDateString(new Date());
ID 格式转换
// 将 Salesforce ID 转换为 15 位格式
public String to15CharId(String salesforceId)
// 将 Salesforce ID 转换为 18 位格式
public String to18CharId(String salesforceId)
// 示例
String id18 = converter.to18CharId("001xx000003DHb2AAG");
String id15 = converter.to15CharId("001xx000003DHb2AAG");
时区支持:
// 使用默认时区(UTC)
SalesforceDataTypeConverter converter1 = new SalesforceDataTypeConverter();
// 使用自定义时区
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
SalesforceDataTypeConverter converter2 = new SalesforceDataTypeConverter(zoneId);
4. SalesforceParam(参数封装类)
类路径: com.datai.common.param.SalesforceParam
功能描述: 封装 Salesforce 查询参数,提供统一的参数传递方式。
主要字段:
| 字段名 | 类型 | 说明 |
|---|---|---|
| api | String | 查询对象 API 名称 |
| select | String | 查询字段 |
| beginDate | Date | 开始日期 |
| endDate | Date | 结束日期 |
| beginCreateDate | Date | 开始创建日期 |
| endCreateDate | Date | 结束创建日期 |
| beginModifyDate | Date | 开始修改日期 |
| endModifyDate | Date | 结束修改日期 |
| maxId | String | 最大 ID |
| idField | String | ID 字段名(默认为 "Id") |
| dateField | String | 日期字段名(默认为 "CreatedDate") |
| sql | String | 自定义 SQL |
| batchId | Integer | 批次 ID |
| isDeleted | Boolean | 是否逻辑删除 |
| limit | Integer | 查询限制数量 |
| isSingleThread | Boolean | 是否单线程(默认为 false) |
使用示例:
SalesforceParam param = new SalesforceParam();
param.setApi("Account");
param.setSelect("Id, Name, CreatedDate");
param.setBeginCreateDate(startDate);
param.setEndCreateDate(endDate);
param.setLimit(100);
5. FileObjectType(文件对象类型枚举)
类路径: com.datai.common.enums.FileObjectType
功能描述: 定义 Salesforce 文件对象类型,提供文件上传相关的元数据。
枚举值:
| 枚举值 | API 名称 | 描述 | 最大大小 | 推荐 | 上传方法 | 必需字段 |
|---|---|---|---|---|---|---|
| ATTACHMENT | Attachment | 传统附件对象(已弃用) | 50 MB | 仅兼容旧系统 | REST API (JSON + Base64) | ParentId, Name, Body |
| CONTENT_DOCUMENT | ContentDocument | 现代文件对象 | 2048 MB | 强烈推荐 | REST API (Multipart/form-data) | Title, PathOnClient, VersionData |
| DOCUMENT | Document | 文档对象 | 25 MB | 仅用于特定遗留功能 | Partner API (SOAP) | FolderId, Name, Body |
使用示例:
// 获取枚举
FileObjectType type = FileObjectType.fromApiName("ContentDocument");
// 获取属性
String apiName = type.getApiName(); // "ContentDocument"
int maxSizeMB = type.getMaxSizeMB(); // 2048
long maxSizeBytes = type.getMaxSizeBytes(); // 2147483648
String recommendation = type.getRecommendation(); // "强烈推荐"
6. 异常体系
异常层次结构:
SalesforceAuthException(认证异常基类)
├── SalesforceLoginException(登录异常)
├── SalesforceLegacyCredentialLoginException(传统凭证登录异常)
├── SalesforceOAuthException(OAuth 异常)
├── SalesforceSessionIdLoginException(Session ID 登录异常)
└── SalesforceCliLoginException(CLI 登录异常)
SalesforceLoginException(登录异常)
├── PasswordExpiredException(密码过期异常)
└── NotLoggedInException(未登录异常)
FileUploadException(文件上传异常)
├── FileSizeExceededException(文件大小超出限制异常)
├── FileTypeNotSupportedException(文件类型不支持异常)
├── FileObjectNotFoundException(文件对象未找到异常)
└── FileValidationException(文件验证异常)
SalesforceOperationException(操作异常)
├── ExtractException(提取异常)
├── LoadException(加载异常)
└── ...
DataAccessException(数据访问异常)
├── DataAccessObjectException(数据访问对象异常)
├── DataAccessRowException(数据访问行异常)
└── ...
ConfigException(配置异常)
├── ConfigInitializationException(配置初始化异常)
├── OrgConfigNotFoundException(组织配置未找到异常)
└── ...
主要异常类:
SalesforceAuthException
// Salesforce 认证异常基类
public class SalesforceAuthException extends RuntimeException {
private String errorCode;
public SalesforceAuthException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
SalesforceLoginException
// Salesforce 登录异常
public class SalesforceLoginException extends SalesforceAuthException {
public SalesforceLoginException(String message) {
super(message);
}
public SalesforceLoginException(String errorCode, String message) {
super(errorCode, message);
}
}
FileUploadException
// 文件上传异常
public class FileUploadException extends RuntimeException {
private FileErrorCode errorCode;
public FileUploadException(FileErrorCode errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public FileErrorCode getErrorCode() {
return errorCode;
}
}
使用示例:
// 抛出登录异常
throw new SalesforceLoginException("LOGIN_FAILED", "登录失败,请检查用户名和密码");
// 抛出文件上传异常
throw new FileUploadException(FileErrorCode.FILE_SIZE_EXCEEDED, "文件大小超出限制");
// 捕获异常
try {
// 执行登录
} catch (SalesforceLoginException e) {
String errorCode = e.getErrorCode();
String message = e.getMessage();
// 处理异常
}
依赖关系
Maven 依赖
<dependencies>
<!-- datai-common:通用工具模块 -->
<dependency>
<groupId>com.datai</groupId>
<artifactId>datai-common</artifactId>
</dependency>
<!-- commons-beanutils:Bean 工具 -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<!-- force-wsc:Force Web Service Connector -->
<dependency>
<groupId>com.force.api</groupId>
<artifactId>force-wsc</artifactId>
<version>61.0.0</version>
</dependency>
<!-- hutool-all:Hutool 工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.22</version>
</dependency>
<!-- fastjson2:JSON 处理 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.60</version>
</dependency>
</dependencies>
模块依赖
被依赖的模块:
- datai-salesforce-auth:使用常量、异常、工具类
- datai-salesforce-partner:使用常量、参数、工具类
- datai-salesforce-apex:使用常量、参数、工具类
- datai-salesforce-metadata:使用常量、参数、工具类
- datai-salesforce-tooling:使用常量、参数、工具类
依赖的模块:
- datai-common:通用工具模块
使用示例
示例 1:使用 SoqlBuilder 构建查询
// 简单查询
String soql1 = new SoqlBuilder()
.select("Id", "Name", "CreatedDate")
.from("Account")
.whereEq("Status", "Active")
.orderBy("CreatedDate", SortOrder.DESC)
.limit(10)
.build();
// 复杂查询
String soql2 = new SoqlBuilder()
.select("Id", "Name", "Account.Name", "TotalAmount", "StageName")
.from("Opportunity")
.whereEq("StageName", "Closed Won")
.whereGe("CloseDate", "2024-01-01")
.whereIn("Type", Arrays.asList("New Customer", "Existing Customer"))
.whereLike("Name", "Project%")
.orderBy("TotalAmount", SortOrder.DESC)
.limit(50)
.build();
// COUNT 查询
String countSoql = new SoqlBuilder()
.select("Id")
.from("Account")
.whereEq("Status", "Active")
.buildCountQuery();
示例 2:使用 SalesforceDataTypeConverter
// 创建转换器(使用默认时区)
SalesforceDataTypeConverter converter = new SalesforceDataTypeConverter();
// 日期时间转换
Date date = converter.convertToDate("2024-01-15T10:30:00.000Z");
String dateTimeStr = converter.convertToString(date);
String dateStr = converter.convertToDateString(date);
// ID 格式转换
String id18 = converter.to18CharId("001xx000003DHb2AAG");
String id15 = converter.to15CharId("001xx000003DHb2AAG");
// 使用自定义时区
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
SalesforceDataTypeConverter converter2 = new SalesforceDataTypeConverter(zoneId);
示例 3:使用 SalesforceParam
// 创建参数对象
SalesforceParam param = new SalesforceParam();
param.setApi("Account");
param.setSelect("Id, Name, CreatedDate, LastModifiedDate");
param.setBeginCreateDate(startDate);
param.setEndCreateDate(endDate);
param.setLimit(100);
param.setIsDeleted(false);
// 使用参数构建查询
String soql = new SoqlBuilder()
.select(param.getSelect().split(",\\s*"))
.from(param.getApi())
.whereGe(param.getDateField(), param.getBeginCreateDate())
.whereLe(param.getDateField(), param.getEndCreateDate())
.whereEq("IsDeleted", param.getIsDeleted())
.limit(param.getLimit())
.build();
示例 4:使用 FileObjectType
// 获取文件对象类型
FileObjectType type = FileObjectType.fromApiName("ContentDocument");
// 获取文件对象属性
String apiName = type.getApiName(); // "ContentDocument"
String description = type.getDescription(); // "现代文件对象"
int maxSizeMB = type.getMaxSizeMB(); // 2048
long maxSizeBytes = type.getMaxSizeBytes(); // 2147483648
String recommendation = type.getRecommendation(); // "强烈推荐"
String uploadMethod = type.getUploadMethod(); // "REST API (Multipart/form-data)"
String requiredFields = type.getRequiredFields(); // "Title, PathOnClient, VersionData"
// 验证文件大小
long fileSize = 1024 * 1024 * 500; // 500 MB
if (fileSize > type.getMaxSizeBytes()) {
throw new FileUploadException(FileErrorCode.FILE_SIZE_EXCEEDED,
"文件大小超出限制,最大允许 " + type.getMaxSizeMB() + " MB");
}
示例 5:使用异常类
// 抛出登录异常
try {
// 执行登录
if (loginResult == null || !loginResult.isSuccess()) {
throw new SalesforceLoginException("LOGIN_FAILED", "登录失败,请检查用户名和密码");
}
} catch (SalesforceLoginException e) {
String errorCode = e.getErrorCode();
String message = e.getMessage();
// 处理异常
logger.error("登录失败: errorCode={}, message={}", errorCode, message);
}
// 抛出文件上传异常
try {
// 上传文件
if (fileSize > maxSize) {
throw new FileUploadException(FileErrorCode.FILE_SIZE_EXCEEDED,
"文件大小超出限制,最大允许 " + maxSize + " MB");
}
} catch (FileUploadException e) {
FileErrorCode errorCode = e.getErrorCode();
String message = e.getMessage();
// 处理异常
logger.error("文件上传失败: errorCode={}, message={}", errorCode, message);
}
// 抛出操作异常
try {
// 执行操作
if (operationResult == null) {
throw new SalesforceOperationException("OPERATION_FAILED", "操作失败");
}
} catch (SalesforceOperationException e) {
String errorCode = e.getErrorCode();
String message = e.getMessage();
// 处理异常
logger.error("操作失败: errorCode={}, message={}", errorCode, message);
}
示例 6:使用常量
// 使用 API 版本常量
String restApiVersion = SalesforceConstants.REST_API_VERSION; // "v59.0"
String bulkV1ApiVersion = SalesforceConstants.BULK_V1_API_VERSION; // "47.0"
String bulkV2ApiVersion = SalesforceConstants.BULK_V2_API_VERSION; // "v59.0"
// 使用端点常量
String restEndpointSuffix = SalesforceConstants.REST_ENDPOINT_SUFFIX; // "/services/data/"
String bulkV1EndpointSuffix = SalesforceConstants.BULK_V1_ENDPOINT_SUFFIX; // "/services/async/"
String bulkV2EndpointSuffix = SalesforceConstants.BULK_V2_ENDPOINT_SUFFIX; // "/services/data/v59.0/jobs/"
// 使用连接类型常量
String soapConnectionType = SalesforceConstants.CONNECTION_TYPE_SOAP; // "SOAP"
String restConnectionType = SalesforceConstants.CONNECTION_TYPE_REST; // "REST"
String bulkV1ConnectionType = SalesforceConstants.CONNECTION_TYPE_BULK_V1; // "BULK_V1"
String bulkV2ConnectionType = SalesforceConstants.CONNECTION_TYPE_BULK_V2; // "BULK_V2"
// 使用 HTTP 方法常量
String httpGet = SalesforceConstants.HTTP_METHOD_GET; // "GET"
String httpPost = SalesforceConstants.HTTP_METHOD_POST; // "POST"
// 使用内容类型常量
String contentTypeJson = SalesforceConstants.CONTENT_TYPE_JSON; // "application/json"
String contentTypeCsv = SalesforceConstants.CONTENT_TYPE_CSV; // "text/csv"
// 使用日期格式常量
String sfDateFormat = SalesforceConstants.SF_DATE_FORMAT; // "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
String sfDateOnlyFormat = SalesforceConstants.SF_DATE_ONLY_FORMAT; // "yyyy-MM-dd"
// 使用批次处理常量
int largeBatchSize = SalesforceConstants.LARGE_BATCH_SIZE; // 10000
int smallBatchSize = SalesforceConstants.SMALL_BATCH_SIZE; // 200
long batchSleepMs = SalesforceConstants.BATCH_SLEEP_MS; // 1L
// 使用重试常量
int maxRetryCount = SalesforceConstants.MAX_RETRY_COUNT; // 3
long retryDelayMs = SalesforceConstants.RETRY_DELAY_MS; // 1000L
最佳实践
1. 使用 SoqlBuilder 构建查询
- 始终使用 SoqlBuilder 构建 SOQL 查询,不要手动拼接字符串
- 利用链式调用提高代码可读性
- 使用类型安全的方法(如 whereEq、whereGt)而不是手动拼接条件
- 注意 SOQL 的限制(如最多返回 50000 条记录,OFFSET 上限为 2000)
2. 使用 SalesforceDataTypeConverter 进行数据转换
- 始终使用 SalesforceDataTypeConverter 进行日期时间转换
- 注意时区问题,根据需要设置正确的时区
- 使用 to18CharId 和 to15CharId 进行 ID 格式转换
3. 使用 SalesforceParam 封装参数
- 使用 SalesforceParam 封装查询参数,提高代码可维护性
- 设置合理的默认值(如 idField、dateField)
- 注意参数验证,防止无效参数
4. 使用 FileObjectType 处理文件上传
- 优先使用 ContentDocument(现代文件对象)
- 注意文件大小限制,上传前验证文件大小
- 使用枚举获取文件对象的元数据
5. 使用异常类处理错误
- 使用合适的异常类,不要使用通用的 RuntimeException
- 提供清晰的错误码和错误消息
- 在合适的层级捕获和处理异常
6. 使用常量避免魔法值
- 使用 SalesforceConstants 中的常量,不要硬编码字符串
- 保持常量的可读性和可维护性
- 按功能模块分类组织常量
常见问题
Q1:SoqlBuilder 支持 SELECT * 吗?
A:不支持。SOQL 不支持 SELECT *,必须明确指定查询字段或使用 FIELDS()。
Q2:SoqlBuilder 支持 BETWEEN 运算符吗?
A:不支持。请使用 >= 和 <= 组合代替 BETWEEN。
Q3:SoqlBuilder 支持 JOIN 吗?
A:不支持。请使用关系查询(Relationship Queries)如 Account.Name。
Q4:SoqlBuilder 支持 UNION 吗?
A:不支持。SOQL 无法合并两个不相关的结果集。
Q5:SoqlBuilder 查询最多返回多少条记录?
A:最多返回 50000 条记录。
Q6:SoqlBuilder 的 OFFSET 上限是多少?
A:OFFSET 上限为 2000,且必须与 LIMIT 一起使用。
Q7:SalesforceDataTypeConverter 支持哪些时区?
A:支持所有 Java 时区。默认使用 UTC 时区,可以通过构造函数指定自定义时区。
Q8:Salesforce ID 的 15 位和 18 位有什么区别?
A:15 位 ID 是不区分大小写的,18 位 ID 包含校验位,可以区分大小写。建议使用 18 位 ID。
Q9:FileObjectType 推荐使用哪种文件对象?
A:强烈推荐使用 ContentDocument(现代文件对象),它支持更大的文件大小(2048 MB)和更好的功能。
Q10:如何选择合适的异常类?
A:根据业务场景选择合适的异常类。例如,登录失败使用 SalesforceLoginException,文件上传失败使用 FileUploadException,操作失败使用 SalesforceOperationException。
总结
datai-salesforce-common 模块是整个 Salesforce 集成体系的基础设施层,提供了丰富的工具类、常量定义、数据转换和异常处理功能。该模块被其他所有 Salesforce 相关模块依赖,是整个体系的基础。
核心优势:
- 统一的常量管理
- 强大的 SOQL 查询构建器
- 完善的数据类型转换
- 丰富的异常体系
- 统一的参数封装
- 类型安全的枚举定义
适用场景:
- 所有与 Salesforce 集成的应用
- 需要 SOQL 查询构建的场景
- 需要数据类型转换的场景
- 需要统一异常处理的场景
- 需要参数封装的场景
- 需要文件上传的场景