You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Salesforce after insert/after update触发器执行顺序控制问题

Salesforce Case触发器插入时触发afterUpdate问题修复

根因说明

  • 你的触发器分支判断逻辑本身没有错误,问题出在DuplicateTicketHandler的afterInsert方法中:你对匹配到的重复子Case执行了update updatedChuld更新操作,该DML会再次触发Case对象的触发器,此时触发的是更新事件,因此会连带执行afterUpdate逻辑。
  • 现有代码额外存在批量逻辑漏洞:afterUpdate方法中遍历newAcc时仅保存了最后一条Case的新旧值,批量操作时逻辑会完全不符合预期。

修复方案

1. 新增静态递归控制变量,拦截重复触发

在Handler类中添加静态布尔变量作为开关,避免同一次事务中触发器被重复调用执行逻辑。

2. 修复批量逻辑适配问题

修改afterUpdate逻辑,适配多条记录批量操作的场景。

3. 优化SOQL查询,减少governor limit消耗

合并重复的SOQL查询,降低资源占用。

修复后完整代码

DuplicateTicketHandler类

public class DuplicateTicketHandler {
    // 事务级递归控制静态变量,默认false允许执行逻辑
    public static Boolean isTriggerExecuting = false;

    public void afterinsert(List<Case> newcase){
        // 递归拦截
        if(isTriggerExecuting) return;
        isTriggerExecuting = true;

        List<String> newNaturofIssue = new List<String>();
        List<String> newFacility = new List<String>();
        List<Case> updatedChuld = new List<Case>();
        Case parentCase;

        for(Case cs : newcase){
            newNaturofIssue.add(cs.Nature_of_issue_Formula__c);
            newFacility.add(cs.Facility_Formula__c);
        }
        // 一次查询拿到所有匹配记录,按创建时间排序
        List<Case> matchCases = [Select Id,Status,createdDate,Nature_of_issue_Formula__c,Facility_Formula__c 
                                 from Case 
                                 where status <> 'closed' 
                                 and Nature_of_issue_Formula__c IN :newNaturofIssue 
                                 and Facility_Formula__c IN :newFacility
                                 order by createdDate asc];
        
        if(matchCases.size() > 1){
            parentCase = matchCases[0];
            // 从第二条开始都是子Case
            for(Integer i=1; i<matchCases.size(); i++){
                matchCases[i].ParentId = parentCase.Id;
                updatedChuld.add(matchCases[i]);
            }
        }  

        System.debug('childupdated===>'+updatedChuld);
        if(updatedChuld.size() > 0){
            update updatedChuld;
        }
        // 重置开关,避免同一次会话后续操作被拦截
        isTriggerExecuting = false;
    }
    
    public void afterUpdate(List<Case> OldAcc , List<Case> newAcc, Map<Id, Case> newCase, Map<Id, Case> oldCase){
        // 递归拦截
        if(isTriggerExecuting) return;
        isTriggerExecuting = true;

        List<String> newNaturofIssue = new List<String>();
        List<String> newFacility = new List<String>();
        List<Case> childtoupdate= new List<Case>();

        for(Case cs : OldAcc){
            newNaturofIssue.add(cs.Nature_of_issue_Formula__c);
            newFacility.add(cs.Facility_Formula__c);
        }

        List<Case> matchCases = [Select Id,Status,createdDate,Nature_of_issue_Formula__c,Facility_Formula__c 
                                 from Case 
                                 where status <> 'Closed'  
                                 and Nature_of_issue_Formula__c IN :newNaturofIssue 
                                 and Facility_Formula__c IN :newFacility
                                 order by createdDate asc];
        if(matchCases.size() <= 1){
            isTriggerExecuting = false;
            return;
        }
        Case parentCase = matchCases[0];
        List<Case> childCases = matchCases.subList(1, matchCases.size());

        Case oldParent = oldCase.get(parentCase.Id);
        Case newParent = newCase.get(parentCase.Id);
        // 父Case属性变化时同步子Case
        if(oldParent != null && newParent != null){
            Boolean needSync = (String.valueOf(oldParent.OwnerId).startsWith('00G') && oldParent.Status == newParent.Status)
                                || (oldParent.Status != newParent.Status);
            if(needSync){
                for(Case child : childCases){
                    child.OwnerId = newParent.OwnerId;
                    child.Status = newParent.Status;
                    childtoupdate.add(child);
                }
            }
        }

        if (childtoupdate.size()>0) {
            update childtoupdate;
        }
        // 重置开关
        isTriggerExecuting = false;
    }
}

DuplicateTicketsTriggerV1触发器

触发器本身的分支判断逻辑无需修改,保持原有代码即可:

trigger DuplicateTicketsTriggerV1 on Case (after insert,after Update) {
    DuplicateTicketHandler dth = new DuplicateTicketHandler();
    if(Trigger.isInsert && Trigger.isAfter){
        dth.afterinsert(Trigger.New);
    }
    else if(Trigger.isAfter && Trigger.isUpdate){
        dth.afterUpdate(Trigger.Old, Trigger.New, trigger.newMap, trigger.oldMap);
    }
}

内容的提问来源于stack exchange,提问作者ambush kumar singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 14:39:02