Batch classes are used to process very large volume of data without hitting Salesforce governor limits. Batch classes should implement "Database.Batchable" interface and it has three methods that must be implemented.
Start
This method executes only once at the start of the batch. It queries all the records that needs to be processed and passes a Database.Querylocator or an iterable of objects to next execute method.Execute
This method gets executed multiple times for one batch invocation. The total number of records that need to be processed from start method is divided into small chunks of batch size(default is 200) and for each chunk execute method is executed one after another. Since each of these chunks get separate execution context, you get separate governor limits for each chunk.Finish
This method gets executed once at the end of the batch. ie after all individual execute chunks are complete. This is usually used for post processing activities like sending email notifying admin that batch executed successfully.Sample - Batch to update number of contacts to account
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************************* | |
* @Name UpdateContactNumberBatch | |
* @Author FirstName LastName <author@email.com> | |
* @Date 09/20/2017 | |
* @Group Apex Batches | |
* @Description This batch class updates a custom field in account with the number of contact | |
* under it | |
*******************************************************************************************/ | |
/* MODIFICATION LOG | |
* Version Developer Date Description | |
*------------------------------------------------------------------------------------------- | |
* 1.0 Firstname 09/20/2017 Initial Creation | |
*******************************************************************************************/ | |
global class UpdateContactNumberBatch implements Database.Batchable<sObject> { | |
/************************************************************************************** | |
* @Description This method gets all the accounts that needs to be processed and returns | |
* a QueryLocator | |
* @Param bc - BatchableContext | |
* @Return Database.QueryLocator - QueryLocator to the queried records | |
**************************************************************************************/ | |
global Database.QueryLocator start(Database.BatchableContext bc) { | |
return Database.getQueryLocator([SELECT Id,Contact_Count__c FROM Account]); | |
} | |
/************************************************************************************** | |
* @Description This method executes aggregate query on contact object and updates | |
* corresponding account with number of contacts under it | |
* @Param bc - BatchableContext | |
* @Param accountList - Chunk of accounts that needs to be processed | |
* @Return NA | |
**************************************************************************************/ | |
global void execute(Database.BatchableContext bc, List<Account> accountList){ | |
//Getting all Ids from list; | |
Set<Id> allAccIdSet = new Map<Id, Account>(accountList).keyset(); | |
List<Account> accUpdateList = new List<Account>(); | |
//Aggregating contacts by accounts | |
for(AggregateResult aggResult: [SELECT AccountId, Count(Id) | |
FROM Contact | |
WHERE AccountId =: accountList | |
GROUP BY AccountId]) { | |
Account acc = new Account(Id = (Id)aggResult.get('AccountId')); | |
acc.Contact_Count__c = (Integer)aggResult.get('expr0'); | |
accUpdateList.add(acc); | |
allAccIdSet.remove(acc.Id); | |
} | |
for(Id accId: allAccIdSet) { | |
accUpdateList.add(new Account(Id = accId, Contact_Count__c = 0)); | |
} | |
update accUpdateList; | |
} | |
/************************************************************************************** | |
* @Description This method executes any post-processing operations | |
* @Param bc - BatchableContext | |
* @Return NA | |
**************************************************************************************/ | |
global void finish(Database.BatchableContext bc){ | |
// execute any post-processing operations | |
} | |
} |
Common use cases for apex batch classes are below,
- Process bulk data that cannot be processed in single execution due to governor limits. For example making updates to more than 10k records.
- If regular execution is hitting heap limit, usually we need to go for batch/future class. Regular heap limit is 6MB. But in asynchronous execution methods like batch or future classes we get a 12MB heap limit
- Making thousands of callouts. Suppose you have to get some details about your accounts from an external system by hitting a webservice during night. You can make only 100 callouts in one transaction.
- Send custom emails(with complex data from multiple objects which is not possible with workflow) to multiple people from apex. Keep batch size 10 as salesforce allows only 10 outbound emails in single transaction
- Make more than 10 Future callouts. Here also keep batch size as 10 because salesforce allows only 10 future callouts in one transaction.
No comments:
Post a Comment