> Apex中文手册 > Apex - Governer Limits调节器限制

控制器执行限制确保在Force.com多租户平台上有效地使用资源。 它是由Salesforce.com指定的对代码执行有效处理的限制。


什么是调节器限制?

我们知道,Apex在多租户环境中运行; 即单个资源由所有客户和组织共享。 因此,有必要确保没有人垄断资源,因此Salesforce.com已经创建了一组管理和限制代码执行的限制。 每当任何一个调节器限制被越过,它将抛出错误,并将停止程序的执行。


从开发人员的角度来看,确保我们的代码是可扩展的并且不应该达到极限是至关重要的。所有这些限制都适用于每个交易。 单个触发器执行一个事务。


正如我们所看到的,触发器设计模式是一种避免极限误差的方法。 让我们看看一些重要的限制。


避免SOQL查询限制

每个事务只能发出100个查询,也就是说,当代码发出超过100个SOQL查询时,它会抛出错误。


例如:

以下是显示如何达到SOQL查询限制的示例:

以下触发器遍历客户列表,并使用字符串“Ok to Pay”更新子记录(发票)描述。

//Heper class:Below code needs o be checked.
public class CustomerTriggerHelper {
	
	public static void isAfterUpdateCall(Trigger.new) {
		createInvoiceRecords(trigger.new);//Method call
		updateCustomerDescription(trigger.new);
	}

	//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
	}

	//Method to update the invoice records
	public static updateCustomerDescription (List<apex_customer__c> customerList) {
		for (APEX_Customer__c objCust: customerList) {
			List<apex_invoice__c> invList = [SELECT Id, Name, APEX_Description__c FROM APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];//This query will fire for the number of records customer list has and will hit the governor limit when records are more than 100 
			for (APEX_Invoice__c objInv: invList) {
				objInv.APEX_Description__c = 'OK To Pay';
				update objInv;//Update invoice, this will also hit the governor limit for DML if large number(150) of records are there
			}
		}
	} 
}

当方法'updateCustomerDescription'被调用,并且客户记录的数量大于100时,它将达到SOQL限制。


为了避免这种情况,不要在For循环中写入SOQL查询。 在这种情况下,SOQL查询已经写入for循环。


下面是我们可以避免DML以及SOQL限制的示例。 我们使用嵌套关系查询来获取发票记录,并使用上下文变量trigger.newMap来获取id和Customer记录的映射。

//SOQL-Good Way to Write Query and avoid limit exception
//Helper Class
public class CustomerTriggerHelper {
	
	public static void isAfterUpdateCall(Trigger.new) {
		createInvoiceRecords(trigger.new);//Method call
		updateCustomerDescription(trigger.new, trigger.newMap);
	}

	//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
	}

	//Method to update the invoice records
	public static updateCustomerDescription (List<apex_customer__c> customerList, Map<id, apex_customer__c> newMapVariable) {
		List<apex_customer__c> customerListWithInvoice = [SELECT id, Name,(SELECT Id, Name, APEX_Description__c FROM APEX_Invoice__r) FROM APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];//Query will be for only one time and fetches all the records
		List<apex_invoice__c> invoiceToUpdate = new List<apex_invoice__c>();
		for (APEX_Customer__c objCust: customerList) {
			for (APEX_Invoice__c objInv: invList) {
				objInv.APEX_Description__c = 'OK To Pay';
				invoiceToUpdate.add(objInv);//Add the modified records to List
			}
		}
		update invoiceToUpdate;
	} 
}

DML批量调用

正如我们在许多示例中看到的,我们一直在列表中添加修改的记录,然后对该列表执行DML操作,而不是对单个记录执行DML。 下面是同样的例子。 这是批量触发器以及触发器帮助器类模式的示例。 您必须先保存帮助程序类,然后保存触发器。


注意:将以下代码粘贴到我们之前创建的“CustomerTriggerHelper”类中。

//Helper Class
public class CustomerTriggerHelper {
    
    public static void isAfterUpdateCall(List<apex_customer__c> customerList, Map<id, apex_customer__c> mapIdToCustomers, Map<id, apex_customer__c> mapOldItToCustomers) {
        createInvoiceRecords(customerList, mapOldItToCustomers);//Method call
        updateCustomerDescription(customerList,mapIdToCustomers, mapOldItToCustomers);
    }

    //Method To Create Invoice Records
    public static void createInvoiceRecords (List<apex_customer__c> customerList, Map<id, apex_customer__c> mapOldItToCustomers) {
        List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
        List<apex_customer__c> customerToInvoice = [SELECT id, Name FROM APEX_Customer__c LIMIT 1];
        for (APEX_Customer__c objCustomer: customerList) {
            if (objCustomer.APEX_Customer_Status__c == 'Active' && mapOldItToCustomers.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';
                objInvoice.APEX_Customer__c = objCustomer.id;
                InvoiceList.add(objInvoice);
            }
        }
        system.debug('InvoiceList&&&'+InvoiceList);
        insert InvoiceList;//DML to insert the Invoice List in SFDC. This also follows the Bulk pattern
    }

    //Method to update the invoice records
    public static void updateCustomerDescription (List<apex_customer__c> customerList, Map<id, apex_customer__c> newMapVariable, Map<id, apex_customer__c> oldCustomerMap) {
        List<apex_customer__c> customerListWithInvoice = [SELECT id, Name,(SELECT Id, Name, APEX_Description__c FROM Invoices__r) FROM APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];//Query will be for only one time and fetches all the records
        List<apex_invoice__c> invoiceToUpdate = new List<apex_invoice__c>();
		List<apex_invoice__c> invoiceFetched = new List<apex_invoice__c>();
		invoiceFetched = customerListWithInvoice[0].Invoices__r;
		system.debug('invoiceFetched'+invoiceFetched);
        system.debug('customerListWithInvoice****'+customerListWithInvoice);
		for (APEX_Customer__c objCust: customerList) {
			system.debug('objCust.Invoices__r'+objCust.Invoices__r);
            if (objCust.APEX_Active__c == true && oldCustomerMap.get(objCust.id).APEX_Active__c == false) {
				for (APEX_Invoice__c objInv: invoiceFetched) {
					system.debug('I am in For Loop'+objInv);
					objInv.APEX_Description__c = 'OK To Pay';
					invoiceToUpdate.add(objInv);//Add the modified records to List
				}
			}
        }
		system.debug('Value of List ***'+invoiceToUpdate);
        update invoiceToUpdate;//This statement is Bulk DML which performs the DML on List and avoids the DML Governor limit
    } 
}

//Trigger Code for this class: Paste this code in 'Customer_After_Insert' trigger on Customer Object
trigger Customer_After_Insert on APEX_Customer__c (after update) {
    CustomerTriggerHelper.isAfterUpdateCall(Trigger.new, trigger.newMap, trigger.oldMap);//Trigger calls the helper class and does not have any code in Trigger
}

其他Salesforce Governor限制

以下是一些重要的Salesforce Governor限制,我们需要记住。 你可以检查其他Salesforce Governor限制以及使用Salesdorce.com Apex开发人员指南。

描述 限制
Total heap size
总堆大小
6 MB / 12 MB
Total number of DML statements issued
发出的DML语句的总数
150
Total number of records retrieved by a single SOSL query
单个SOSL查询检索的记录总数
2000
Total number of SOSL queries issued
发出的SOSL查询的总数
20
Total number of records retrieved by Database.getQueryLocator
Database.getQueryLocator检索的记录总数
10000
Total number of records retrieved by SOQL queries
通过SOQL查询检索的记录总数
50000