Salesforce配置存储对决 Custom Settings与Custom Metadata Types场景选择深度解析
核心概念解析
Custom Settings(自定义设置)
Custom Metadata Types(自定义元数据类型 - CMDT)
关键差异深度对比
决策框架:何时选择哪一个?
高级考量与实践建议
总结
在Salesforce平台上构建复杂应用时,如何高效、可靠地管理配置信息至关重要。这些配置可能包括API端点、功能开关、映射值、业务规则参数等等。Salesforce为此提供了几种机制,其中最常用的是Custom Settings(自定义设置)和Custom Metadata Types(自定义元数据类型,简称CMDT)。
虽然它们都能存储数据,但其底层机制、部署方式、访问模式和适用场景却大相径庭。对于架构师和高级开发者来说,理解这些差异并做出明智的选择,直接影响到应用的可维护性、可部署性和性能。你是不是也曾在List Custom Setting、Hierarchy Custom Setting和CMDT之间犹豫不决?别担心,这篇文章将深入剖析这三者的核心区别和最佳实践,帮你彻底搞清楚何时该用哪个。
核心概念解析
在深入比较之前,我们先快速回顾一下这三个工具的基本概念。
Custom Settings(自定义设置)
自定义设置本质上更像是数据,虽然它们提供了一些优于自定义对象存储配置的优势。它们允许你创建自定义的数据集,并能在Apex、公式字段、验证规则、Flow等地方快速访问,关键在于访问它们不计入SOQL查询限制,因为Salesforce会将这些设置缓存起来。
Custom Settings主要有两种类型:
List Custom Settings(列表自定义设置)
- 结构: 提供一组静态数据,类似于一个没有记录类型、只有组织级别访问权限的自定义对象。每条设置记录有唯一的名称字段(Name)和自定义字段。
- 用途: 存储组织级别的、不经常变动的列表数据。例如,国家代码与国家名称的映射、产品分类代码等。
- 访问: 主要通过Apex的
CustomSettingName__c.getAll()
返回Map<String, CustomSettingName__c>,或CustomSettingName__c.getInstance(dataSetName)
获取特定记录。 - 特点: 数据是全局共享的,没有用户或简档级别的区分。
Hierarchy Custom Settings(层级自定义设置)
- 结构: 具有内置的层级逻辑,允许你为特定用户、特定简档(Profile)或整个组织定义不同的设置值。Salesforce会根据当前用户的上下文自动查找最具体的设置。
- 层级顺序: Salesforce查找设置值的顺序是:当前用户 -> 用户简档 -> 组织默认值。找到第一个匹配项即返回。
- 用途: 实现基于用户或角色的个性化配置。例如,为特定用户或部门开启某个Beta功能、设置不同的API调用次数限制、控制特定用户群体的UI元素可见性等。
- 访问: 主要通过Apex的
CustomSettingName__c.getInstance()
(自动根据上下文获取)、CustomSettingName__c.getOrgDefaults()
、CustomSettingName__c.getInstance(userId)
、CustomSettingName__c.getInstance(profileId)
。 - 特点: 强大的层级覆盖能力,但数据仍然是数据。
Custom Metadata Types(自定义元数据类型 - CMDT)
CMDT是Salesforce推荐的现代应用配置管理方式。与Custom Settings最大的不同在于,CMDT被视为元数据(Metadata),而不是数据。
- 结构: 类似于自定义对象,可以定义自定义字段(包括关系字段、选项列表、复选框等,比Custom Settings支持的类型更丰富)。每条记录有Label和Developer Name。
- 用途: 存储应用程序的核心配置信息,这些信息通常与代码一起打包和部署。例如,集成服务的端点URL和认证信息、复杂的业务规则定义、动态页面布局的配置、映射表等。
- 访问: 可以通过SOQL直接查询,并且读取操作不计入SOQL查询限制!也可以通过Apex的
getAll()
、getInstance(recordId)
、getInstance(developerName)
方法访问。 - 特点:
- 可部署: 作为元数据,CMDT记录可以通过变更集(Change Sets)、Metadata API、SFDX等工具在不同环境(沙箱、生产)之间轻松部署,无需手动导入数据或运行脚本。
- 治理性强: 元数据天然支持版本控制和更严格的部署流程。
- 关系字段: 可以创建指向其他CMDT或标准/自定义对象的元数据关系字段,构建更复杂的配置结构。
- 包容性: 可以包含在托管或非托管包中。
关键差异深度对比
理解了基本概念后,让我们把这三者放在一起,进行一次全方位的对比。这部分是决策的关键。
特性 | List Custom Setting | Hierarchy Custom Setting | Custom Metadata Type (CMDT) |
---|---|---|---|
本质 | 数据 (Data) | 数据 (Data) | 元数据 (Metadata) |
部署方式 | 手动数据加载 / Apex脚本 / 数据加载工具 | 手动数据加载 / Apex脚本 / 数据加载工具 | 变更集 / Metadata API / SFDX / 包 |
访问方式 | Apex getAll() , getInstance(name) |
Apex getInstance() , getOrgDefaults() 等 |
SOQL (读不计入限制), Apex getAll() , getInstance() |
缓存机制 | 应用服务器缓存 (Application Server Cache) | 应用服务器缓存 (Application Server Cache) | 元数据缓存 (Metadata Cache) |
层级逻辑 | 无 | 用户 > 简档 > 组织 | 无内置层级 (可通过关系字段模拟) |
字段类型 | 基本类型 (文本, 数字, 日期, 复选框等) | 基本类型 (同List) | 更丰富 (包括选项列表, 关系字段等) |
SOQL查询限制 | 不适用 (非SOQL访问) | 不适用 (非SOQL访问) | 读取操作不计入SOQL查询限制 |
DML限制 | 受DML行数和语句限制 | 受DML行数和语句限制 | 创建/更新/删除受元数据部署限制 (非DML) |
记录访问控制 | 公开读写 (通过“管理自定义设置”权限控制) | 公开读写 (通过“管理自定义设置”权限控制) | 通过简档/权限集控制元数据API访问 |
测试类支持 | 需要在测试类中创建数据 (@isTest(SeeAllData=true) 或手动插入) |
需要在测试类中创建数据 (同List) | 记录在测试类中默认可见 (因为是元数据) |
关系能力 | 无 | 无 | 可创建元数据关系字段 |
打包能力 | 仅设置定义可打包,数据需手动处理 | 仅设置定义可打包,数据需手动处理 | 定义和记录均可打包 |
深入解读几个关键点:
- 数据 vs. 元数据: 这是最根本的区别。元数据意味着配置是应用定义的一部分,随代码一起版本控制、部署和管理。数据则需要独立于代码进行管理,增加了环境同步的复杂性。
- 部署: CMDT的元数据特性使其在DevOps流程中具有巨大优势。想象一下,你更新了一个API端点,使用CMDT,这个变更可以无缝地通过CI/CD管道推送到各个环境。而使用Custom Settings,你可能需要在每个环境手动更新,或者编写复杂的数据迁移脚本,容易出错且效率低下。
- 访问与Governor Limits: 虽然Custom Settings访问不计入SOQL查询,但CMDT通过SOQL访问同样不计入查询限制(仅限读取),这使得CMDT在需要复杂查询或筛选配置数据时更加灵活,同时保持了高性能。例如,你可以用WHERE子句轻松过滤CMDT记录。Custom Settings的
getAll()
会加载所有记录到内存,对于非常大的数据集可能存在内存隐患,而SOQL查询CMDT则更可控。 - 层级逻辑: Hierarchy Custom Setting的内置层级是其独特优势,对于需要基于用户/简档进行精细化控制的场景非常方便。CMDT虽然没有内置层级,但可以通过在CMDT上添加用户/简档查找字段,然后在Apex或Flow中实现类似的逻辑,虽然需要额外编码,但提供了更大的灵活性。
- 测试: CMDT记录在测试类中默认可见,极大地简化了单元测试的编写。测试Custom Settings则通常需要创建测试数据,或者(不推荐地)使用
@isTest(SeeAllData=true)
。
决策框架:何时选择哪一个?
好了,理论和对比都清楚了,现在是最实际的问题:面对具体需求,到底该选谁?
选择 List Custom Settings 当:
- 你需要存储组织级别的、相对静态的键值对或列表数据。
- 数据不需要作为应用程序元数据的一部分进行部署(例如,可以通过管理员界面轻松维护)。
- 配置逻辑简单,不需要基于用户或简档的层级覆盖。
- 更新频率不高,或者可以接受手动更新或简单脚本更新。
- 实例: 邮政编码与地区的映射、国家代码列表、固定的转换率(如果不需要部署)。
- 思考: “这更像是一份全局参考数据清单吗?” 如果是,List Custom Setting可能是个简单直接的选择。
选择 Hierarchy Custom Settings 当:
- 你需要根据用户或简档提供不同的配置值。
- 层级覆盖逻辑(用户 > 简档 > 组织)完全符合你的需求。
- 数据不需要作为应用程序元数据的一部分进行部署。
- 允许管理员或特定用户能够方便地为自己或他人调整设置。
- 实例: 为特定支持团队开启调试日志记录、控制不同用户组看到的功能模块、设置用户个性化的默认记录类型。
- 思考: “这个设置需要因人而异,并且Salesforce的默认层级查找能满足我吗?” 如果是,Hierarchy Custom Setting是首选。
选择 Custom Metadata Types (CMDT) 当:
- 配置信息是应用程序核心逻辑的一部分,需要与代码一起打包和部署。
- 你需要利用变更集、Metadata API 或 SFDX 在不同环境间迁移配置。
- 你需要更丰富的字段类型,特别是关系字段来构建复杂的配置结构。
- 你需要通过SOQL 查询配置数据(例如,在Apex或Flow中根据条件动态获取配置),并且希望避免SOQL查询限制。
- 你需要对配置记录进行更严格的治理和版本控制。
- 配置数据需要在单元测试中轻松访问而无需创建测试数据。
- 你需要构建可分发的应用程序包(Managed/Unmanaged Package)。
- 实例: 存储集成服务的端点、密钥和超时设置;定义复杂的折扣规则引擎参数;管理动态流程或UI元素的配置;存储国家/地区特定的验证规则。
- 思考: “这个配置是应用代码运行的基础吗?我需要像部署代码一样部署它吗?我需要更复杂的结构或查询能力吗?” 如果答案是肯定的,那么CMDT几乎总是更好的选择。
高级考量与实践建议
- 性能: 三者都利用了缓存机制,访问速度通常很快。CMDT的元数据缓存通常被认为更健壮。对于大量记录(成千上万条),CMDT的SOQL查询可能比
getAll()
加载整个List Custom Setting更高效。 - 安全性: Custom Settings的记录级访问通常是公开的,其安全性主要通过“管理自定义设置”权限来控制谁可以修改定义和数据。CMDT的记录访问可以通过元数据API的权限控制,并且可以在Apex中实现更细粒度的逻辑控制。
- 迁移路径: 如果你现有应用大量使用了Custom Settings,并且遇到了部署或管理的痛点,可以考虑逐步迁移到CMDT。这可能需要编写一次性的迁移脚本,并重构访问这些配置的代码(从Apex方法调用改为SOQL查询或CMDT的Apex方法)。
- Flow 和 Process Builder: 这三种机制都可以在Flow和Process Builder中访问,但方式略有不同。CMDT可以通过Get Records元素使用SOQL查询,非常灵活。Custom Settings通常通过公式或Apex Action访问。
- 未来趋势: Salesforce 明显在持续投入和推荐使用CMDT作为配置管理的首选方案。新功能和优化更可能出现在CMDT上。
总结
选择正确的配置存储机制是Salesforce应用架构设计中的一个重要环节。简单回顾一下:
- List Custom Settings: 适用于简单的、组织级别的、非层级的、不需要元数据部署的“数据”列表。
- Hierarchy Custom Settings: 适用于需要基于用户/简档进行层级覆盖的、不需要元数据部署的“数据”设置。
- Custom Metadata Types (CMDT): 适用于需要作为元数据进行部署、版本控制和管理的应用程序配置,提供更强的灵活性、治理能力和查询能力,是现代Salesforce开发中管理配置的首选和推荐方式。
下次当你需要存储配置信息时,问自己:它是应用定义的一部分吗?需要和代码一起部署吗?需要层级逻辑吗?需要复杂的查询或关系吗?通过回答这些问题,结合本文的分析,相信你能自信地做出最佳选择,构建出更健壮、更易于维护的Salesforce应用。