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语句限制 是调速器极限。 我们将在后面章节详细介绍Governor Limits。
为了避免这种情况,我们必须使触发器有效地一次处理多个记录。
下面是相同的最佳实践范例:
//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类,并将处理从Trigger委派给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 List<apex_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 } }