Why use Database.stateful in Batch Apex
Each execution receives a new copy of variables and objects in the Batch apex. Since the batch class is stateless by default. It is impossible to utilize past execution values in a new execution. Consequently, static variables lose their value over time.
Therefore, we need to create a database if we wish to use variables that keep their values and use them in the execution and complete methods. stateful as defined by the class.
Related Post: How To Create Lightning Flows In Salesforce – Step By Step Guide
How To Use Database.Stateful Interface In Batch Apex In Salesforce
To utilize Batch Apex, we must first comprehend that we must create an Apex Class that implements the Salesforce-provided interface Database. Batchable, then programmatically call the class. Enter “Apex Jobs” in the Quick Find box under Setup to monitor or halt the execution of the batch Apex task. Then, select Apex Jobs.
The Syntax for Batch
global class BatchName implements Database.Batchable{}
Methods of Batch Class:
global (Database.QueryLocator | Iterable) start (Database.BatchableContext bc) {
//Here we will add the query and return the result to execute method
}
global void execute (Database.BatchableContext BC, list<P>){
//Logic must be here
}
global void finish (Database.BatchableContext BC){
//after processing of all batches this method will be called. We can write any code inside it. Like if want to send email to all the records which are created or updated in the execute method.
}
How to Implement the Database.Batchable Interface
Example
global class BatchAccountUpdate implements Database.Batchable{
String query = 'Select Name from Account WHERE Name! = null AND (Name = \'Virendra Company\' OR Name = \'Virendra Sharma\') ';
global Database.QueryLocator start (Database.BatchableContext bc) {
// collect the batches of records or objects to be passed to execute
return Database.getQueryLocator(query);
}
global void execute (Database.BatchableContext bc, List records) {
// process each batch of records
for (Account acc : records){
acc.Name = acc.Name + ' Updated';
}
update records;
}
global void finish (Database.BatchableContext bc){
// execute any post-processing operations, Calling batch class.
BatchUpdateAccountRelatedContacts b = new BatchUpdateAccountRelatedContacts();
Database.executeBatch(b, 200);
}
}

Database.Stateful
The subsequent sample class uses a QueryLocator to locate all the account data given by the start() function and then changes the related contacts with the postal address of their respective accounts. Since we are utilizing a database.stateful, it then sends an email with the results of the bulk process to track the number of updated records and the state.
Example:
global class UpdateContactAddresses implements
Database.Batchable<sObject>, Database.Stateful {
// instance member to retain state across transactions
global Integer recordsProcessed = 0;
global Database.QueryLocator start (Database.BatchableContext bc) {
return Database.getQueryLocator(
'SELECT ID, BillingStreet, BillingCity, BillingState, ' +
'BillingPostalCode, (SELECT ID, MailingStreet, MailingCity, ' +
'MailingState, MailingPostalCode FROM Ccntacts) FROM Account' +
'Where BillingCountry =
global void execute (Database.BatchableContext bc, List<Account> scope){
// process each batch of records
List<Contact> contacts = new List<Contact>O;
for (Account account : scope) {
for (Contact contact : account.contacts) {
contact.MailingStreet = account.BillingStreet;
contact.MailingCity = account.BillingCity;
contact.MailingState = account.BillingState;
contact.MailingPostalCode = account.BillingPostalCode;
// add contactto list to be updated
contacts.add(contact);
// incrementthe instance member counter
recordsProcessed = recordsProcessed + 1;
update contacts;
global void finish (Database.BatchableContext bc){
System.debug(recordsProcessed + ' records processed. Shazam!');
AsyncApexJob job = [SELECT ld, Status, NumberOfErrors,
JobltemsProcessed,
TotalJobItems, CreatedBy.Email
FROM AsyncApexJob
WHERE ld = :bc.getJ0bldO];
// call some utility to send email
EmailUtils.sendMessage(job, recordsProcessed);
Database.AllowsCallout
Database. AllowsCallout in Batch facilitates the connection of Salesforce to a remote or external server. To use a callout in batch Apex, We need to utilize an interface Database. AllowsCallouts in the batch class’s class definition.
The Syntex
global class SearchAndReplace implements Database.Batchable, Database.AllowsCallouts{}
Example:
Here, We are integrating the Opportunity object with Skedulo.com
/*
Get service requests from Skedulo and update them in the salesforce.
*/
global class Batch_SR_SkeduloAPI implements Database.Batchable, Database.AllowsCallouts{ global Database.QueryLocator start (Database.BatchableContext BC){ String query = 'SELECT Id, Octalsoftware_Service_Request_Id__c FROM Opportunity WHERE Skedulo_Service_Request_Id__c != null AND Skedulo_Job_Status__c != \'Job Done\' AND Skedulo_Status__c = \'Success\''; return Database.getQueryLocator(query); } global void execute (Database.BatchableContext BC, List scope){ String StatusId = ''; for (Opportunity s : scope){ //get ServiceRequest System.debug(s.Id); Http http1 = new Http(); HttpRequest request1 = new HttpRequest(); request1.setEndpoint('https://DomainName.0.Skedulo.com/ApiService.svc/ServiceRequest/'+ s.Skedulo_Service_Request_Id__c); request1.setMethod('GET'); request1.setHeader('Content-Type', 'application/json'); request1.setHeader('Host', 'DomainName.0.Skedulo.com'); request1.setHeader('Content-Length', '0'); request1.setHeader('Connection', 'Keep-Alive'); request1.setHeader('ServerName', 'DomainServerName'); request1.setHeader('Token', 'XXXXXXXXXXXXXXXXXXXXXXX'); HttpResponse response1 = http1.send(request1); if(response1.getStatusCode() == 200) { StatusId = ''; JSONParser parser = JSON.createParser(response1.getBody()); while(parser.nextToken() != null) { if( (parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'StatusId') || Test.isRunningTest()) { parser.nextToken(); StatusId = parser.getText(); } } System.debug(StatusId); if(StatusId == String.valueOf(1) || Test.isRunningTest()){ s.Skedulo_Job_Status__c = 'Job Done'; s.StageName = 'Closed Won'; }else{ s.Skedulo_Job_Status__c = 'Working'; } } } update scope; } global void finish (Database.BatchableContext BC){ } }
And this is how we use Database.Stateful In Batch Apex.
Looking for salesforce consulting services? Let’s connect and discuss your exciting project.