salesforce零基礎學習(一百二十七)Custom Metadata Type 篇二

zero.zhang發表於2023-03-15

本篇參考:

 salesforce零基礎學習(一百一十一)custom metadata type資料獲取方式更新

https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_custom_metadata_types.htm

https://help.salesforce.com/s/articleView?id=sf.custommetadatatypes_overview.htm&language=en_US&type=5

https://trailhead.salesforce.com/content/learn/modules/custom_metadata_types_dec/cmt_overview

https://developer.salesforce.com/docs/atlas.en-us.224.0.apexcode.meta/apexcode/apex_class_Metadata_Operations.htm

我們在之前的篇中簡單描述了 custom metadata type的使用,最開始的 custom metadata type是來建議取代 list custom setting,好處是可以基於metadata進行部署,不用像custom setting基於資料方式,容易出現漏部署情況,所以基於當時的版本來說, custom metadata type相對 list custom setting來說好處是基於metadata部署避免遺漏。

隨著 custom metadata type的不斷升級,目前增加了很多吸引人的點,主要是針對 Metadata Relationship欄位型別的展開,接下來我們看一下這個新的型別可以實現的內容和場景。

一. Metadata Relationship型別

當我們在 custom metadata type建立欄位時,目前欄位型別增加了Metadata Relationship型別,此種型別可以設定兩類的關聯關係。

  • 關聯到其他的custom metadata type,比如metadata type中維護省和市的資訊,可以在市的metadata type中關聯到省的metadata type。

  • 關聯到salesforce標準的表或者自定義表/欄位的例項中,比如關聯到 Account表的 Industry欄位(場景可以基於配置方式設定 default value)。

 當我們點選此型別建立的下一步,會讓你選擇系統已經存在的 custom metadata type還是選擇 Entity Definition。需要注意的是,如果你的系統曾經已經建立過 Entity Definition,那樣以後的步驟中,還會再列表中可以選擇 Field Definition以及Entity Particle,這個在下面圖中會有涉及。

demo中會建立這兩種型別,其中關聯自定義 metadata type的建立步驟不在此處羅列,主要講一下 Entity Definition相關的關聯,當我們建立了關聯到 Entity Definition的欄位以後,我們繼續建立 Metadata Relationship型別的欄位,就可以看到下圖內容。其中:

  • Field Definition:關聯的是上述選定的表的標準或者自定義欄位
  • Entity Particle:關聯的是上述選定的表的標準欄位中的複合型別欄位或者地理資訊型別欄位。

 當我們選擇 Field Definition型別以後,點選下一步會選擇 controling field,這樣就會實現當選擇某個表資訊以後,就可以選擇到當前這個表的欄位。

 當我們建立表相關的表資料以後,我們就可以為custom metadata type設定資料,下圖demo中維護了Account Customer Priority(自定義欄位)預設值的一條資料,我們可以看到當Object Name選擇了 Account以後,Field Name就可以自動的基於Account(作為 controling field)選擇到 Account表中的欄位。

這裡針對父子的場景不做一步一步處理,感興趣的可以基於下圖進行資料的建立。

二. Custom Metadata Type使用場景介紹

1. 欄位default value: 我們在專案上,有時需要在欄位級別或者後臺程式碼設定欄位的預設值。原有方式是可以基於型別進行設定,比如picklist可以透過選擇,其他型別就在 Default Value處設定初始值。apex端設定可以透過Custom Label或者hardcode方式寫。除此以外,我們建議使用 Custom Metadata Type來統一維護初始值設定。UI方面可以基於指定的寫法進行設定,格式如下圖所示。

 

2. 用於validation rule / formula / process builder:這裡只針對validation rule進行舉例,寫法相同。舉個例子,當系統validation rule需要配置的規則用於很多表,並且這個值可能是動態修改的,我們不能每次變更都修改所引用到的所有的validation rule,這時我們可以基於custom metadata type進行配置來更好的可配置化管理。

 三. 透過apex class獲取 custom metadata type

1. 獲取 field Definition型別的metadata type資料

基於 apex端,我們可以透過基於metadata的方式,或者基於SOQL搜尋方式獲取到這條資料,然後獲取這條資料的資訊,下方的demo僅供參考。

 1). 透過 custom metadata type的getInstance方式獲取。此方法前提是你需要了解到這個metadata type的 Name資訊。

Default_Value__mdt defaultValue = Default_Value__mdt.getInstance('Account_Customer_Priority_Default');
system.debug('*** default value: ' + defaultValue.Default_Value__c);

2). 透過表欄位的名稱獲取(這裡程式碼可以進行最佳化,目前demo中的場景為有且僅有一條配置)。這裡我們透過 FieldDefinition獲取了當前表的 DurableId,原因是custom metadata type返回的 Field Definition是 DurableId,這個表會在下一篇部落格做一些介紹。

List<Default_Value__mdt> defaultValueList = Default_Value__mdt.getAll().values();

Default_Value__mdt defaultValue;

List<FieldDefinition> fieldDefinitionList = [SELECT Id, DeveloperName, DurableId 
                                                FROM FieldDefinition  
                                                WHERE DeveloperName = 'Customer_Priority' 
                                                AND EntityDefinition.QualifiedApiName = 'Account'];
//TODO 實際專案中禁止此種寫法,需要非空判斷
String customerPriorityDurableId = fieldDefinitionList.get(0).DurableId;

for(Default_Value__mdt valueItem : defaultValueList) {
    if('Account'.equalsIgnorecase(valueItem.Object_Name__c) 
        && customerPriorityDurableId.equalsIgnorecase(valueItem.Field_Name__c)) {
        defaultValue = valueItem;
    }
}

if(defaultValue != null) {
    system.debug('*** default value : ' + defaultValue.Default_Value__c);
}

2. 獲取到關聯其他metadata type的資料

1). 透過 custom metadata type的getInstance方式獲取,方式同上,不做說明。

 2) 透過關聯父表的資料的developerName進行獲取(這裡程式碼可以進行最佳化,目前demo中的場景為有且僅有一條配置)。

List<Default_Value__mdt> defaultValueList = Default_Value__mdt.getAll().values();

Default_Value__mdt targetDefaultValue;

for(Default_Value__mdt valueItem : defaultValueList) {
    if(String.isNotBlank(valueItem.Parent_Metadata_Type__c) 
        && 'test_parent'.equalsIgnorecase(valueItem.Parent_Metadata_Type__r.DeveloperName)) {
        targetDefaultValue = valueItem;
    }
}

system.debug(JSON.serialize(targetDefaultValue));

我們看一下目標資料透過 getAll返回的JSON結構,我們會發現如果有負責結構內容,會將復結構的資訊同樣返回。

{
    "MasterLabel": "TEST_RELATION_WITH_PARENT", 
    "NamespacePrefix": null, 
    "QualifiedApiName": "TEST_RELATION_WITH_PARENT", 
    "Parent_Metadata_Type__c": "m005g000002FMry", 
    "Language": "zh_CN", 
    "attributes": {
        "type": "Default_Value__mdt", 
        "url": "/services/data/v57.0/sobjects/Default_Value__mdt/m025g000000rtgz"
    }, 
    "DeveloperName": "TEST_RELATION_WITH_PARENT", 
    "Id": "m025g000000rtgz", 
    "Parent_Metadata_Type__r": {
        "attributes": {
            "type": "Parent_Metadata_Type__mdt"
        }, 
        "DeveloperName": "test_parent"
    }, 
    "Field_Name__c": null, 
    "Object_Name__c": null, 
    "Label": "TEST_RELATION_WITH_PARENT", 
    "SystemModstamp": "2023-03-15T10:00:03.000+0000", 
    "Default_Value__c": null
}

總結:本篇主要是介紹了一下 metadata type除取代list custom setting以外的其他的使用場景以及使用apex獲取的方式。篇中的demo也僅用於獲取資料用,對判斷,邏輯,可行性操作都可以進一步最佳化。篇中有錯誤地方歡迎指出,有不懂歡迎留言。

相關文章