Apex-governor-limits
Apex-ガバナーの制限
ガバナーの実行制限により、Force.comマルチテナントプラットフォーム上のリソースを効率的に使用できます。 これは、効率的な処理のためのコード実行に関してSalesforce.comによって指定された制限です。
ガバナー制限とは何ですか?
知っているように、Apexはマルチテナント環境で実行されます。つまり、単一のリソースがすべての顧客と組織で共有されます。 したがって、誰もリソースを独占しないようにする必要があります。したがって、Salesforce.comは、コード実行を管理および制限する一連の制限を作成しました。 ガバナーの制限のいずれかを超えると、エラーがスローされ、プログラムの実行が停止します。
開発者の観点からは、コードがスケーラブルであり、制限に達していないことを確認することが重要です。
これらの制限はすべて、トランザクションごとに適用されます。 単一のトリガーの実行は1つのトランザクションです。
これまで見てきたように、トリガー設計パターンは制限エラーを回避するのに役立ちます。 他の重要な制限が表示されます。
SOQLクエリ制限の回避
トランザクションごとに発行できるクエリは100のみです。つまり、コードが100を超えるSOQLクエリを発行すると、エラーがスローされます。
例
この例は、SOQLクエリの制限に到達する方法を示しています-
次のトリガーは、顧客のリストを反復処理し、子レコード(請求書)の説明を文字列「Ok to Pay」で更新します。
//Helper 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_customer__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一括呼び出し
この例は、バルクトリガーとトリガーヘルパークラスパターンを示しています。 最初にヘルパークラスを保存してから、トリガーを保存する必要があります。
注-以前に作成した「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ガバナーのその他の制限
次の表に、重要なガバナーの制限を示します。
Description | Limit |
---|---|
Total heap size | 6 MB/12 MB |
Total number of DML statements issued | 150 |
Total number of records retrieved by a single SOSL query | 2000 |
Total number of SOSL queries issued | 20 |
Total number of records retrieved by Database.getQueryLocator | 10000 |
Total number of records retrieved by SOQL queries | 50000 |