- Apex编程教程
- Apex - 首页
- Apex - 概述
- Apex - 环境
- Apex - 示例
- Apex - 数据类型
- Apex - 变量
- Apex - 字符串
- Apex - 数组
- Apex - 常量
- Apex - 决策
- Apex - 循环
- Apex - 集合
- Apex - 类
- Apex - 方法
- Apex - 对象
- Apex - 接口
- Apex - DML
- Apex - 数据库方法
- Apex - SOSL
- Apex - SOQL
- Apex - 安全性
- Apex - 调用
- Apex - 触发器
- Apex - 触发器设计模式
- Apex - 限制
- Apex - 批量处理
- Apex - 调试
- Apex - 测试
- Apex - 部署
- Apex有用资源
- Apex - 快速指南
- Apex - 资源
- Apex - 讨论
Apex - 触发器设计模式
设计模式用于使我们的代码更有效率,并避免触犯限制。开发人员经常会编写低效的代码,这可能导致对象重复实例化。这可能导致代码效率低下、性能不佳,并可能违反限制。这最常发生在触发器中,因为它们可以针对一组记录进行操作。
我们将在本章中了解一些重要的设计模式策略。
批量触发器设计模式
在实际业务案例中,您可能需要一次处理数千条记录。如果您的触发器没有设计成处理这种情况,那么它在处理记录时可能会失败。在实现触发器时,需要遵循一些最佳实践。所有触发器默认都是批量触发器,并且可以一次处理多条记录。您应该始终计划一次处理多条记录。
考虑一个业务案例,您需要处理大量记录,并且您已编写如下所示的触发器。这是我们之前为在客户状态从“非活动”更改为“活动”时插入发票记录而采用的相同示例。
// Bad Trigger Example
trigger Customer_After_Insert on APEX_Customer__c (after update) {
for (APEX_Customer__c objCustomer: Trigger.new) {
if (objCustomer.APEX_Customer_Status__c == 'Active' &&
trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
// condition to check the old value and new value
APEX_Invoice__c objInvoice = new APEX_Invoice__c();
objInvoice.APEX_Status__c = 'Pending';
insert objInvoice; //DML to insert the Invoice List in SFDC
}
}
}
您现在可以看到,DML语句已编写在for循环块中,这在处理少量记录时有效,但当您处理数百条记录时,它将达到每个事务的DML语句限制,即**限制**。我们将在后续章节中详细介绍限制。
为了避免这种情况,我们必须使触发器能够有效地一次处理多条记录。
以下示例将帮助您理解这一点:
// Modified Trigger Code-Bulk Trigger
trigger Customer_After_Insert on APEX_Customer__c (after update) {
List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
for (APEX_Customer__c objCustomer: Trigger.new) {
if (objCustomer.APEX_Customer_Status__c == 'Active' &&
trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
//condition to check the old value and new value
APEX_Invoice__c objInvoice = new APEX_Invoice__c();
objInvoice.APEX_Status__c = 'Pending';
InvoiceList.add(objInvoice);//Adding records to List
}
}
insert InvoiceList;
// DML to insert the Invoice List in SFDC, this list contains the all records
// which need to be modified and will fire only one DML
}
此触发器只会触发1个DML语句,因为它将作用于一个列表,并且该列表包含所有需要修改的记录。
通过这种方式,您可以避免DML语句限制。
触发器辅助类
在触发器中编写所有代码也不是一个好的实践。因此,您应该调用Apex类并将处理从触发器委托给Apex类,如下所示。触发器辅助类是执行触发器所有处理的类。
让我们再次考虑我们的发票记录创建示例。
// Below is the Trigger without Helper class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
for (APEX_Customer__c objCustomer: Trigger.new) {
if (objCustomer.APEX_Customer_Status__c == 'Active' &&
trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
// condition to check the old value and new value
APEX_Invoice__c objInvoice = new APEX_Invoice__c();
objInvoice.APEX_Status__c = 'Pending';
InvoiceList.add(objInvoice);
}
}
insert InvoiceList; // DML to insert the Invoice List in SFDC
}
// Below is the trigger with helper class
// Trigger with Helper Class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
CustomerTriggerHelper.createInvoiceRecords(Trigger.new, trigger.oldMap);
// Trigger calls the helper class and does not have any code in Trigger
}
辅助类
public class CustomerTriggerHelper {
public static void createInvoiceRecords (List<apex_customer__c>
customerList, Map<id, apex_customer__c> oldMapCustomer) {
List<apex_invoice__c> InvoiceList = new Listvapex_invoice__c>();
for (APEX_Customer__c objCustomer: customerList) {
if (objCustomer.APEX_Customer_Status__c == 'Active' &&
oldMapCustomer.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
// condition to check the old value and new value
APEX_Invoice__c objInvoice = new APEX_Invoice__c();
// objInvoice.APEX_Status__c = 'Pending';
InvoiceList.add(objInvoice);
}
}
insert InvoiceList; // DML to insert the Invoice List in SFDC
}
}
在此,所有处理都已委托给辅助类,当我们需要新的功能时,我们可以简单地将代码添加到辅助类中,而无需修改触发器。
每个sObject上的单个触发器
始终在每个对象上创建一个触发器。如果同一对象上的多个触发器达到限制,则可能导致冲突和错误。
您可以使用上下文变量根据需要从辅助类调用不同的方法。考虑我们之前的示例。假设我们的createInvoice方法仅在记录更新且在多个事件上时才应被调用。然后,我们可以如下控制执行:
// Trigger with Context variable for controlling the calling flow
trigger Customer_After_Insert on APEX_Customer__c (after update, after insert) {
if (trigger.isAfter && trigger.isUpdate) {
// This condition will check for trigger events using isAfter and isUpdate
// context variable
CustomerTriggerHelper.createInvoiceRecords(Trigger.new);
// Trigger calls the helper class and does not have any code in Trigger
// and this will be called only when trigger ids after update
}
}
// Helper Class
public class CustomerTriggerHelper {
//Method To Create Invoice Records
public static void createInvoiceRecords (List<apex_customer__c> customerList) {
for (APEX_Customer__c objCustomer: customerList) {
if (objCustomer.APEX_Customer_Status__c == 'Active' &&
trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
// condition to check the old value and new value
APEX_Invoice__c objInvoice = new APEX_Invoice__c();
objInvoice.APEX_Status__c = 'Pending';
InvoiceList.add(objInvoice);
}
}
insert InvoiceList; // DML to insert the Invoice List in SFDC
}
}