Wednesday, September 12, 2018

Batch class in salesforce

Batch class in Salesforce:Today we will try to cover concepts of Batch apex.


When we want to deal with large number of records we go for batch apex. The code inside batch class runs asynchronously i.e in future context. The governor limit are also more as compared to synchronous code. 


Batch class in Salesforce

When we use batch apex we implements Database.batchable() interface 


The Database.batchable() contains three methods that we need to defined inside batch class and they are, 
1)start 
2)execute 
3)Finish 

Start method and finish method are called only once inside batch class. 

  • Start method collects the data for processing. 
  • Execute method performs operations. 
  • Finish method generally used for sending emails or calling another batch class when the current batch is completed. 

Syntax:

global class batch implements Database.Batchable < sObject > { 



global (Database.QueryLocator or  Iterable<sObject>)

start(Database.BatchableContext bc) { 

//query on object; 

//return Database.getQueryLocator(query); 




global void execute(Database.batchableContext bc, List < SObject > scope) { 


//some processing. 



global void finish(Database.BatchableContext bc) { 

//job such as sending email or calling another batch class 







POINTS TO REMEMBER:



Batch apex


  • use Database.getQueryLocator when you are using simple query to create scope for object in batch job.
  • use Iterable<sObject> when you have complex criterion to process the record.
  • If we use query locator object governor limit is bypassed.
  • If we use Iterable<sObject> governor limit is enforced.
  • The order of execution is not guaranteed in execute method.
  • If the batch is executed without the optional scope parameter and If in batch apex suppose we have 600 jobs and there are total 200 records to be proceeds in each transaction,so in total we have 3 transaction.If first transaction succeeds but second fails so in this case the records update done in first transaction are not rolled back.
Number of batches and scope size:

When  an apex job is executed by setting some value for scope size it is not necessary that the number of record processed in one batch iteration will be same as that of scope size specified.

Records from the query locator are retrieved in chunks of given chunk size called retrieveChunkSize .

Chunks size available are 100,200,400.

Selection of chunk size depends on the scope size specified.

If 1 <= scopeSize <= 100, then retrieveChunkSize = 100
If 101 <= scopeSize <= 400, then retrieveChunkSize = 400
If 401 <= scopeSize <= 2000, then retrieveChunkSize = 2000


So Let say if we 285 records to be proceeds and we specify the scope size as 80 than the retrieveChunkSize  will be 100.

In this case the total number of batches will note be 4 i.e (285/80) but in this case it would be 3 retrieve chunks and 6 execute chunks so the total number of batches will be 6.

1. Retrieve chunk 1: retrieve first 100 records
 
Execute chunk 1: pass first 80 records to execute() method
Execute chunk 2: pass remaining 20 records from this retrieve chunk to execute() method

2. Retrieve chunk 2: retrieve next 100 records

Execute chunk 3: pass first 80 records to execute() method
Execute chunk 4: pass remaining 20 records from this retrieve chunk to execute() method

3. Retrieve chunk 3: retrieve next 85 records

Execute chunk 5: pass first 80 records to execute() method
Execute chunk 6: pass remaining 5 records from this retrieve chunk to execute() method


Using stateful in batch apex,

If we implements Database.Stateful we can maintained state across transactions.
Only instance variable holds values static members does not hold values.If we want to count records as batch proceeds maintaining state is important as after one transaction new transaction will start and members will loose their values.


SAMPLE BATCH CLASS,

global class updateNameOfAccount implements Database.Batchable<sObject>
{
  String email='test@gmail.com';
    global Database.QueryLocator start(Database.BatchableContext BC)
    {

        String query = 'SELECT Id,Name FROM Account limit 400 ';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Account> scope) {
     

       
        for(Account acc : scope)
        {     
         
            acc.Name = acc.Name + 'Batchupdate';
        }
        update scope;
       
    } 
    global void finish(Database.BatchableContext BC)
    {
 
        AsyncApexJob job = [SELECT Id, Status FROM AsyncApexJob WHERE Id = :BC.getJobId()];
         //Sending mail about batch status.......
 
    }
 
 

}

To run the above batch class,

Paste the below code in developer console,


updateNameOfAccount obj=new updateNameOfAccount();
Database.executeBatch(obj);


SCHEDULING APEX JOB,

To Schedule the batch class  you need a class which implements schedulable interface,


global class schedulebatch implements schedulable{

   global void execute(Schedulablecontext sc)
          {
             updateNameOfAccount acc=new updateNameOfAccount();
             //Database.executeBatch(instance,size);
             Database.executeBatch(acc,200);
          }

}

Now,you can schedule class schedulebatch  from User Interface,

Setup>develop>apex classes> schedule apex.


HOW TO DO REST API CALLOUT FROM BATCH APEX,

global class updateNameOfAccount1 implements Database.Batchable<sObject>,Database.AllowsCallouts
{
  String email='test@gmail.com';
  string searchtext='techacc';
    global Database.QueryLocator start(Database.BatchableContext BC)
    {

        String query = 'SELECT Id,Name,description FROM Account where name like \'%'+searchtext+'%\'  limit 1 ';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Account> scope) {
     
Http http=new Http();

HttpRequest req=new HttpRequest();

req.setEndpoint('http://ip.jsontest.com/');

req.setMethod('GET');     //  Get data


HttpResponse res=http.send(req);

string response1=res.getBody();


 for(Account acc : scope)
        {     
         
            acc.description= acc.description + response1;
        }
        update scope;

     
    }
    global void finish(Database.BatchableContext BC)
    {
 
        AsyncApexJob job = [SELECT Id, Status FROM AsyncApexJob WHERE Id = :BC.getJobId()];
         //Sending mail about batch status.......
 
    }

    }

HOW TO GET FAILURE RECORDS IN BATCH APEX,

USE the below code in execute method,


Global set<id> FailureRecId;
Database.saveresult[] result=database.insert(scope,false);
for(Database.saveresult res:result)
{
if(res.isSuccess())
{

}
else{
for(Database.Error failrec:res.getErrors())
{
FailureRecId.add(failrec.getID());
}
}

}

Methods available with  SaveResult method,

getErrors() // Returns an array of one or more database error objects.
getId() // Returns Id of sObject we are trying to update.
isSuccess() // Returns true if operation was successfull.

CALLING BATCH CLASS FROM APEX,

public class someName{
             updateNameOfAccount acc=new updateNameOfAccount();  // Batch class name
             Database.executeBatch(acc);
}

**************************************************************************************************************

TAGS:Using Batch Apex ,Batch Apex,what is Batch Apex,How to write Batch Class in Salesforce,Apex Batch Processing,Salesforce Batch Apex,batch class in salesforce,scheduler class in salesforce.

**************************************************************************************************************


1 comment: