Apex类添加After Update实现联系人数量汇总字段更新
问题描述
我写了以下Apex类和触发器,用于在Contact添加或移除关联Account时,更新Account层级的Number_of_Contacts__c字段,目的是在Account报表中展示每个Account关联的Contact数量。由于Salesforce不支持Account到Contact的汇总字段,且Flow只能处理Contact创建或删除场景,所以用Apex实现。现有代码能处理AFTER_INSERT、AFTER_DELETE、AFTER_UNDELETE操作,但不知道怎么添加AFTER_UPDATE触发器逻辑,实现Contact更换关联Account时更新Number_of_Contacts__c字段,之前尝试没成功。
现有代码
ContactTriggerHandler类
public without sharing class ContactTriggerHandler { private Set<Id> getAccountIds(List<Contact> contacts) { Set<Id> accountIds = new Set<Id>(); for(Contact c : contacts) { if(c.AccountId != null) { accountIds.add(c.AccountId); } } return accountIds; } private Map<Id, Account> getAccountMap(Set<Id> accountIds) { return new Map<Id, Account>([SELECT Id, Number_of_Contacts__c FROM Account WHERE Id in :accountIds]); } public void process(List<Contact> contacts, System.TriggerOperation operation) { Set<Id> accountIds = getAccountIds(contacts); if(accountIds.size() > 0) { Map<Id, Account> accountMap = getAccountMap(accountIds); for(Contact c : contacts) { if(accountMap.containsKey(c.AccountId)) { switch on operation{ when AFTER_INSERT { accountMap.get(c.AccountId).Number_of_Contacts__c += 1; } when AFTER_DELETE { accountMap.get(c.AccountId).Number_of_Contacts__c -= 1; } when AFTER_UNDELETE { accountMap.get(c.AccountId).Number_of_Contacts__c += 1; } } } } update accountMap.values(); } } }
ContactTrigger触发器
trigger ContactTrigger on Contact (after insert, after delete, after undelete) { ContactTriggerHandler handler = new ContactTriggerHandler(); switch on Trigger.operationType { when AFTER_INSERT { handler.process(Trigger.new, Trigger.operationType); } when AFTER_DELETE { handler.process(Trigger.old, Trigger.operationType); } when AFTER_UNDELETE { handler.process(Trigger.new, Trigger.operationType); } } }
解决方案
要处理Contact更换Account的场景,需要同时操作旧关联Account和新关联Account:旧Account的联系人数减1,新Account的联系人数加1。具体修改如下:
1. 修改触发器,添加after update触发事件
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) { ContactTriggerHandler handler = new ContactTriggerHandler(); switch on Trigger.operationType { when AFTER_INSERT { handler.process(Trigger.new, Trigger.operationType); } when AFTER_DELETE { handler.process(Trigger.old, Trigger.operationType); } when AFTER_UNDELETE { handler.process(Trigger.new, Trigger.operationType); } when AFTER_UPDATE { // 传递新旧记录集合给新增的处理方法 handler.processUpdate(Trigger.new, Trigger.oldMap); } } }
2. 在Handler类中新增processUpdate方法,并调整辅助逻辑
public without sharing class ContactTriggerHandler { private Set<Id> getAccountIds(List<Contact> contacts) { Set<Id> accountIds = new Set<Id>(); for(Contact c : contacts) { if(c.AccountId != null) { accountIds.add(c.AccountId); } } return accountIds; } // 新增方法:收集所有需要更新的新旧AccountId private Set<Id> getOldAndNewAccountIds(List<Contact> newContacts, Map<Id, Contact> oldContactMap) { Set<Id> accountIds = new Set<Id>(); for(Contact newC : newContacts) { Contact oldC = oldContactMap.get(newC.Id); // 添加旧AccountId(如果存在) if(oldC.AccountId != null) { accountIds.add(oldC.AccountId); } // 添加新AccountId(如果存在) if(newC.AccountId != null) { accountIds.add(newC.AccountId); } } return accountIds; } private Map<Id, Account> getAccountMap(Set<Id> accountIds) { return new Map<Id, Account>([SELECT Id, Number_of_Contacts__c FROM Account WHERE Id in :accountIds]); } public void process(List<Contact> contacts, System.TriggerOperation operation) { Set<Id> accountIds = getAccountIds(contacts); if(accountIds.size() > 0) { Map<Id, Account> accountMap = getAccountMap(accountIds); for(Contact c : contacts) { if(accountMap.containsKey(c.AccountId)) { switch on operation{ when AFTER_INSERT { accountMap.get(c.AccountId).Number_of_Contacts__c += 1; } when AFTER_DELETE { accountMap.get(c.AccountId).Number_of_Contacts__c -= 1; } when AFTER_UNDELETE { accountMap.get(c.AccountId).Number_of_Contacts__c += 1; } } } } update accountMap.values(); } } // 新增处理Contact更新的方法 public void processUpdate(List<Contact> newContacts, Map<Id, Contact> oldContactMap) { Set<Id> accountIds = getOldAndNewAccountIds(newContacts, oldContactMap); if(accountIds.size() == 0) return; Map<Id, Account> accountMap = getAccountMap(accountIds); for(Contact newC : newContacts) { Contact oldC = oldContactMap.get(newC.Id); Id oldAccountId = oldC.AccountId; Id newAccountId = newC.AccountId; // 仅当AccountId发生变化时执行计数调整 if(oldAccountId != newAccountId) { // 旧Account联系人数减1(如果存在) if(oldAccountId != null && accountMap.containsKey(oldAccountId)) { accountMap.get(oldAccountId).Number_of_Contacts__c -= 1; } // 新Account联系人数加1(如果存在) if(newAccountId != null && accountMap.containsKey(newAccountId)) { accountMap.get(newAccountId).Number_of_Contacts__c += 1; } } } update accountMap.values(); } }
关键说明
- 新增
getOldAndNewAccountIds方法,确保不会遗漏任何需要调整计数的Account(包括旧关联和新关联的)。 processUpdate方法仅在Contact的AccountId实际变化时执行操作,避免无效更新。- 覆盖三种核心更新场景:
- Contact从关联A Account改为关联B Account:A减1,B加1。
- Contact从关联Account改为无关联:原Account减1。
- Contact从无关联改为关联Account:新Account加1。
内容的提问来源于stack exchange,提问作者Andréa Aline
相关产品推荐
相关产品推荐

