Introduction
Batch Apex is used to process large data sets asynchronously by breaking them into manageable chunks.
Key Features
- Processes up to 50 million records.
- Uses three methods:
start
,execute
, andfinish
.
Batch Apex with SObject and Dynamic SOQL
Use Case
To fetch data dynamically using a SOQL query.
Example: Dynamic Query with SObjects
global class BatchWithDynamicQuery implements Database.Batchable<SObject> {
global Database.QueryLocator start(Database.BatchableContext context) {
String query = 'SELECT Id, Name FROM Contact WHERE CreatedDate = LAST_N_DAYS:30';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext context, List<SObject> scope) {
for (SObject record : scope) {
Contact con = (Contact)record;
con.Description = 'Processed in last 30 days';
}
update scope;
}
global void finish(Database.BatchableContext context) {
System.debug('Dynamic Query Batch Completed!');
}
}
Execution
BatchWithDynamicQuery batch = new BatchWithDynamicQuery();
Database.executeBatch(batch, 100); // Process in chunks of 100 records
Batch Apex with Iterable (Database.Iterable)
In Salesforce Batch Apex, you can use an Iterable
instead of a query when you need more control over the records or data being processed. The start
method can return an object of type Iterable
or Iterator
to feed data into the batch process.
Why Use an Iterable?
- You want to process non-SObject data (e.g., custom collections or external API data).
- You need to create records dynamically without using SOQL.
- You have a dataset that isn’t directly queryable using SOQL.
Use Case
When processing data not retrieved via SOQL (e.g., custom data structures, strings, or API results).
Batch Class Using Iterable
Syntax
A Batch Apex class using an Iterable
looks like this:
global class BatchWithIterableExample implements Database.Batchable<String> {
// Start method returns an Iterable
global Iterable<String> start(Database.BatchableContext BC) {
List<String> data = new List<String>{'Record 1', 'Record 2', 'Record 3'};
return data;
}
// Process each chunk of data
global void execute(Database.BatchableContext BC, List<String> scope) {
for (String record : scope) {
System.debug('Processing: ' + record);
}
}
// Finish method for post-processing or notifications
global void finish(Database.BatchableContext BC) {
System.debug('Batch Processing Completed!');
}
}
How to Execute a Batch with Iterable
You can execute the batch as follows:
BatchWithIterableExample batch = new BatchWithIterableExample();
Database.executeBatch(batch, 1); // Process 1 record at a time
When to Use Batch with Iterable
- Dynamic Datasets: When the dataset cannot be fetched via SOQL.
- Non-SObject Processing: For processing strings, numbers, or any other non-SObject data.
- API Integrations: When you need to batch process data fetched from an external system.
- Custom Record Construction: For datasets that are dynamically built at runtime.
Batch Apex: Stateful vs Stateless
Stateful Batch Apex
Use Case
Preserve state (variables) across batch transactions.
Key
Implement the Database.Stateful
interface.
Example: Stateful Batch
global class StatefulBatchExample implements Database.Batchable<SObject>, Database.Stateful {
public Integer processedRecords = 0;
global Database.QueryLocator start(Database.BatchableContext context) {
return Database.getQueryLocator('SELECT Id, Name FROM Account');
}
global void execute(Database.BatchableContext context, List<SObject> scope) {
for (SObject record : scope) {
Account acc = (Account)record;
acc.Name += ' - Processed';
processedRecords++;
}
update scope;
}
global void finish(Database.BatchableContext context) {
System.debug('Total Records Processed: ' + processedRecords);
}
}
Execution
StatefulBatchExample batch = new StatefulBatchExample();
Database.executeBatch(batch, 200); // Process in chunks of 200 records
Stateless Batch Apex
Use Case
No need to maintain variables or state between executions.
Key
Default behavior (does not implement Database.Stateful
).
Example: Stateless Batch
global class StatelessBatchExample implements Database.Batchable<SObject> {
global Database.QueryLocator start(Database.BatchableContext context) {
return Database.getQueryLocator('SELECT Id, Name FROM Account');
}
global void execute(Database.BatchableContext context, List<SObject> scope) {
for (SObject record : scope) {
Account acc = (Account)record;
acc.Name += ' - Updated';
}
update scope;
}
global void finish(Database.BatchableContext context) {
System.debug('Stateless Batch Completed!');
}
}
Execution
StatelessBatchExample batch = new StatelessBatchExample();
Database.executeBatch(batch, 200); // Process in chunks of 200 records
Batch Apex with API Callouts
Use Case
Perform API callouts during batch processing.
Key
- Implement
Database.AllowsCallouts
interface. - Perform callouts in the
execute
method.
Example: Callout in Batch
global class BatchWithCallouts implements Database.Batchable<SObject>, Database.AllowsCallouts {
global Database.QueryLocator start(Database.BatchableContext context) {
return Database.getQueryLocator('SELECT Id, Name FROM Account');
}
global void execute(Database.BatchableContext context, List<SObject> scope) {
for (SObject record : scope) {
Account acc = (Account)record;
// Example API Callout
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/data');
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
acc.Description = 'API Callout Successful';
}
}
update scope;
}
global void finish(Database.BatchableContext context) {
System.debug('Batch with Callouts Completed!');
}
}
Execution
BatchWithCallouts batch = new BatchWithCallouts();
Database.executeBatch(batch, 50); // Process in chunks of 50 records
Summary of Batch Features:
Type | Stateful/Stateless | Iterable Support | Use Case |
---|---|---|---|
Batch with SOQL | Stateless | No | Processing large SObject datasets |
Batch with Iterable | Stateless | Yes | Custom non-SObject datasets |
Stateful Batch | Stateful | Yes | Maintaining variables across transactions |
Stateless Batch | Stateless | Yes | No need for state retention |
Batch with Callouts | Stateless/Stateful | Yes | Performing API callouts during batch processing |
Limitation for Asynchronous
From / What | Call @future method | System.enqueueJob() | Database.executeBatch() | System.schedule() |
---|---|---|---|---|
Anonymous Apex | 50 | 50 | 100 | 100 |
@AuraEnabled method | 50 | 50 | 100 | 100 |
@future method | 0 | 1 | 0 | 100 |
Queueable execute() | 50 | 1 | 100 | 100 |
Schedulable execute() | 50 | 50 | 100 | 100 |
Batch start() | 0 | 1 | 0 | 100 |
Batch execute() | 0 | 1 | 0 | 100 |
Batch finish() | 0 | 1 | 0 | 100 |
Platform Event trigger | 50 | 50 | 100 | 100 |