salesforce的触发器(trigger)

简述

可以使用触发器调用Apex。Apex触发器使您能够在更改Salesforce记录之前或之后执行自定义操作,如插入、更新或删除。
触发器是在以下类型的操作之前或之后执行的Apex代码:

  • insert
  • update
  • delete
  • merge
  • upsert
  • undelete

Upsert触发器:
Upsert操作会触发插入(insert)或更新(update)触发器的执行。对于upsert(插入或更新)操作,相关的触发器会在适当的时机触发——即在执行插入时会触发before insert和after insert触发器,在执行更新时会触发before update和after update触发器。
Merge触发器:
Merge操作(合并)涉及两个记录的合并。在合并操作中,"losing records"(丢失的记录)会触发删除相关的触发器(before delete和after delete),而"winning record"(保留的记录)会触发更新相关的触发器(before update和after update)。这有助于处理合并过程中丢失和保留记录的操作。
触发器有两种类型:
1.Before触发器:在记录保存到数据库之前运行,用于更新或验证记录的值。
2.After触发器:在记录保存后运行,用于访问系统设置的字段值(例如记录的ID或LastModifiedDate字段),并可以影响其他记录的更改。
触发器代码中的静态限制
触发器代码中 不能包含 static 关键字。因为Trigger类的执行是针对每个事件进行的,静态变量无法保证每个事件都独立,因此触发器代码中不支持静态变量的使用。

触发器示例

需求

我们会创建一个触发器,执行以下操作:
1.当创建或更新 Account(账户)记录时,自动创建一个新的 Task(任务),提醒负责人跟进该账户。
2.触发器要处理批量操作,确保不会因为大量记录而超出 Salesforce 的 Governor Limits。

触发器代码示例

trigger AccountTriggerAboutTask on Account (after insert, after update) {

    // 创建一个任务列表,用于批量插入任务记录
    List<Task> tasksToInsert = new List<Task>();
    
    // 遍历所有被插入或更新的账户记录
    for (Account acc : Trigger.new) {
        
        // 只在账户名字包含tasktest的时候
        if (acc.Name != null && acc.Name.toLowerCase().contains('tasktest'.toLowerCase())) {
            
            // 创建一个新的 Task 对象
            Task t = new Task();
            
            // 设置任务的相关字段
            t.Subject = 'Follow up on Account: ' + acc.Name;
            t.WhatId = acc.Id; // 任务与账户相关联
            t.OwnerId = acc.OwnerId; // 任务分配给账户的负责人
            t.Status = 'Not Started'; // 任务初始状态为“未开始”
            t.Priority = 'High'; // 设置任务优先级为“高”
            t.ActivityDate = System.today().addDays(7); // 设置任务的截止日期为7天后
            
            // 将任务添加到待插入列表中
            tasksToInsert.add(t);
        }
    }

    // 如果有待插入的任务记录,批量插入
    if (!tasksToInsert.isEmpty()) {
        insert tasksToInsert;
    }
}

代码解析

触发器声明
触发器 AccountTrigger 是在 Account 对象上执行的,触发器的事件包括 after insert 和 after update。这意味着触发器会在 Account 记录被插入或更新之后执行。
遍历触发的记录
Trigger.new 是一个包含当前操作中所有记录的列表。我们使用 for 循环来遍历每一条记录。如果账户名字包含tasktest的时候,则创建一个任务记录。
创建 Task 任务记录
创建 Task 对象并设置它的字段,如:
Subject:任务的主题,我们设置为 "Follow up on Account: [账户名]"。
WhatId:指向相关的账户记录(通过 acc.Id)。
OwnerId:任务负责人,我们将它设置为账户的负责人 acc.OwnerId。
Status:任务状态设置为“Not Started”。
Priority:任务的优先级设置为“High”。
ActivityDate:任务的截止日期设置为当前日期之后 7 天。
批量插入任务记录
最后,所有待插入的任务记录被收集在 tasksToInsert 列表中。如果列表不为空,则执行批量插入操作 insert tasksToInsert。

注意事项

批量处理:该触发器在设计时考虑到了批量处理。即使用户一次插入或更新多个账户记录,它也会批量处理任务插入,确保不会违反 Salesforce 的 Governor Limits(如每批插入记录的数量限制)。
触发器事件:此触发器是在 after insert 和 after update 阶段触发的,因此在创建或更新账户记录后,相关任务才会被创建。

Trigger上下文变量

Apex Trigger中封装了多个上下文变量,这些变量帮助开发者判断当前操作的状态。常见的上下文变量如下:

1.isExecuting:指示当前Apex代码是否在Trigger环境中执行。如果是Trigger环境,返回true,否则返回false。
2.isInsert:指示当前操作是否为插入操作。如果是插入操作,返回true,否则返回false。
3.isUpdate:指示当前操作是否为更新操作。如果是更新操作,返回true,否则返回false。
4.isDelete:指示当前操作是否为删除操作。如果是删除操作,返回true,否则返回false。
5.isBefore:指示当前操作是否在保存(save)之前执行。如果是before操作,返回true,否则返回false。
6.isAfter:指示当前操作是否在保存(save)之后执行。如果是after操作,返回true,否则返回false。
7.isUndelete:指示当前操作是否在恢复回收箱中的记录后执行。如果是恢复操作,返回true,否则返回false。

特殊的Trigger变量

Trigger中常用的记录变量包括:
new:返回最新记录的列表,仅在insert或update操作的before触发器中可用。
newMap:返回一个包含记录ID与其最新数据的映射(Map)。适用于before update、after insert和after update触发器。
old:返回操作前的记录列表,仅在update和delete操作时可用。
oldMap:返回一个包含记录ID与操作前数据的映射(Map)。适用于update和delete操作。

使用限制

new:只能在insert和update操作的before触发器中使用。
newMap:只能在before update、after insert和after update触发器中使用。
old:仅适用于update和delete操作。
oldMap:仅适用于update和delete操作。

功能模块化

TriggerExecutionHelper 类

public without sharing class TriggerExecutionHelper {
    
    // 控制功能F1是否启用
    public static Boolean enableExecuteF1 {
        get{
            if(enableExecuteF1 == null) {
                enableExecuteF1 = true; // 默认为启用
            }
            return enableExecuteF1;
        }
        set;
    }
    
    // 控制功能F2是否启用
    public static Boolean enableExecuteF2 {
        get{
            if(enableExecuteF2 == null) {
                enableExecuteF2 = true; // 默认为启用
            }
            return enableExecuteF2;
        }
        set;
    }
}

CompanyInfoTrigger 触发器

trigger CompanyInfoTrigger on Company_Info__c (after delete, after insert, after undelete, after update, before delete, before insert, before update) {
    
    // 创建触发器事件对象
    Triggers companyInfoTrigger = new Triggers();
    
    // 检查是否启用功能F1,如果启用则绑定 F1Handler 到 BeforeInsert 事件
    if(TriggerExecutionHelper.enableExecuteF1) {
        companyInfoTrigger.bind(Triggers.Evt.BeforeInsert, new F1Handler());
    }
    
    // 检查是否启用功能F2,如果启用则绑定 F2Handler 到 BeforeInsert 事件
    if(TriggerExecutionHelper.enableExecuteF2) {
        companyInfoTrigger.bind(Triggers.Evt.BeforeInsert, new F2Handler());
    }
    
    // 执行触发器事件
    companyInfoTrigger.Execute();
}

处理器类 (示例)

假设你有两个处理类 F1Handler 和 F2Handler,他们分别处理触发器的不同逻辑。

public class F1Handler {
    public void execute(List<Company_Info__c> records) {
        // 执行F1功能的逻辑
        for (Company_Info__c record : records) {
            record.Name = record.Name + ' - Updated by F1';
        }
    }
}

public class F2Handler {
    public void execute(List<Company_Info__c> records) {
        // 执行F2功能的逻辑
        for (Company_Info__c record : records) {
            record.Industry__c = 'Technology';
        }
    }
}

代码分析

1.TriggerExecutionHelper 类:

  • 这个类提供了两个布尔值静态属性 enableExecuteF1 和 enableExecuteF2,用于控制是否启用 F1 和 F2 功能。
  • 使用 get 方法判断属性是否为 null,若为 null 则默认将其设置为 true。这确保了即使没有显式设置属性,功能依然可以正常工作。

2.CompanyInfoTrigger 触发器:

  • 在触发器中,我们根据 TriggerExecutionHelper 中的静态属性决定是否绑定特定的处理类 (F1Handler 或 F2Handler)。
  • 例如,只有当 TriggerExecutionHelper.enableExecuteF1 为 true 时,F1Handler 才会被绑定到触发器事件上。

3.处理器类(F1Handler 和 F2Handler):

  • 这些类负责在触发器中触发相应的业务逻辑,如更新 Company_Info__c 记录的字段值。每个处理器类都有一个 execute 方法,该方法接受一个记录列表并对其进行处理。

可扩展性与灵活性

  • 启用/禁用功能:你可以在触发器执行之前,根据实际需要启用或禁用某些功能,只需要设置 TriggerExecutionHelper.enableExecuteF1 或 TriggerExecutionHelper.enableExecuteF2。
  • 业务逻辑独立性:每个处理器类(如 F1Handler 和 F2Handler)都相对独立,便于管理和扩展。如果有更多功能需要添加,只需要创建新的处理类并将其与触发器事件绑定即可。
  • 便于测试:通过将触发器处理逻辑拆分到不同的处理类,你可以为每个处理类编写单独的测试类,简化了测试工作。

总结

这种方法通过使用 TriggerExecutionHelper 来动态控制哪些功能需要执行,保证了代码的灵活性和可扩展性。同时,触发器事件通过 bind动态绑定不同的功能处理类,使得系统更加模块化,便于维护和扩展。

posted @ 2025-02-09 17:02  贵gui  阅读(126)  评论(0)    收藏  举报