Salesforce Apex触发器批量更新Fund金额异常及Map解决方案需求
解决Salesforce批量导入Opportunity时Fund金额汇总错误的问题
我一眼就瞅出问题所在了——你的汇总逻辑只处理了单个Fund记录,不管批量导入时关联了多少个不同的Fund,最后都只会更新查询到的第一条Fund,这就是为什么所有金额都跑到第一条记录里的原因。咱们用Map来分组每个Fund对应的Opportunity总金额,就能完美解决批量场景的问题。
原代码的核心问题
- 查询
Fund__c时,明明用了WHERE Id = :oppIds(这里应该是IN更准确),却只赋值给单个Fund__c对象,SOQL返回多条记录时只会取第一条,直接丢失了其他Fund的数据。 - 汇总金额时只针对单个Fund的Opportunity计算,完全没考虑多Fund的批量场景。
修改后的触发器(触发器本身无需大改)
触发器可以保持原有逻辑,咱们重点优化逻辑处理类:
trigger newLeadTrigger on Opportunity (after insert , after update, after delete , after undelete) { if(trigger.isAfter && (trigger.isInsert || trigger.isUpdate || trigger.isUndelete)){ OpportunityCustomRollup.CountRollup(Trigger.new); } if(Trigger.isDelete) { OpportunityCustomRollup.CountRollup(Trigger.old); } }
修改后的控制器类(核心优化)
public class OpportunityCustomRollup { public static void CountRollup(List<Opportunity> lstOpportunity){ // 收集所有关联的有效Fund ID Set<Id> fundIds = new Set<Id>(); for (Opportunity opp : lstOpportunity){ if(opp.Fund__c != null){ fundIds.add(opp.Fund__c); } } // 提前获取Fund Raising类型的RecordType ID,避免循环内查询 Id fundRTRecordTypeId = [SELECT Id FROM RecordType WHERE DeveloperName ='Fund_Raising'].Id; // 用Map存储每个Fund对应的总金额,key为Fund ID,value为汇总后的金额 Map<Id, Double> fundToTotalAmountMap = new Map<Id, Double>(); // 用SOQL聚合查询直接按Fund分组计算总金额,高效且避免冗余循环 List<AggregateResult> aggResults = [ SELECT Fund__c, SUM(Amount) totalAmount FROM Opportunity WHERE Fund__c IN :fundIds AND StageName = 'Closed Won' AND RecordTypeId = :fundRTRecordTypeId GROUP BY Fund__c ]; // 将聚合结果存入Map,方便后续快速匹配 for(AggregateResult ar : aggResults){ Id fundId = (Id)ar.get('Fund__c'); Double total = (Double)ar.get('totalAmount'); fundToTotalAmountMap.put(fundId, total != null ? total : 0.0); } // 查询所有需要更新的Fund记录 List<Fund__c> fundsToUpdate = [SELECT Id, Total_opportunity_amount__c FROM Fund__c WHERE Id IN :fundIds]; // 给每个Fund设置对应的汇总金额 for(Fund__c fund : fundsToUpdate){ fund.Total_opportunity_amount__c = fundToTotalAmountMap.get(fund.Id) != null ? fundToTotalAmountMap.get(fund.Id) : 0.0; } // 批量更新Fund记录,符合Salesforce最佳实践,避免DML超限 if(!fundsToUpdate.isEmpty()){ update fundsToUpdate; } } }
关键优化点
- 用Set收集所有关联Fund ID:确保不会遗漏任何需要更新的Fund记录。
- SOQL聚合查询替代循环计算:通过
GROUP BY直接计算每个Fund的总金额,性能更优且代码更简洁。 - Map映射Fund与金额的对应关系:完美解决多Fund的分组问题,每个Fund的金额不会串线。
- 批量DML更新:一次性更新所有需要修改的Fund,符合Salesforce的DML限制,避免触发单条DML的性能问题。
这样修改后,不管你批量导入多少个关联不同Fund的Opportunity,每个Fund的Total_opportunity_amount__c都会被准确更新,不会再出现所有金额都跑到第一条记录的情况了。
内容的提问来源于stack exchange,提问作者Dharmik Thummar
相关产品推荐
相关产品推荐

