Batch APEX

Batch Apex

Benefits – to stay within governing limits, to allow partial processing of batch of records in case one batch fails to process successfully, all other batch transactions aren’t affected and aren’t rolled back if they were processed successfully.

Default batch size is 200 records.

To write a batch Apex class, your class must implement the Database.Batchable interface. Your class declaration must include the implements keyword followed by Database.Batchable<sObject> and then invoke the class programmatically.
To monitor or stop the execution of the batch Apex job, from Setup, click Monitoring | Apex Jobs or Jobs | Apex Jobs.
The Database.Batchable interface contains three methods that must be implemented:

  1. start method: called at the beginning o the batch apex job. It collects records or objects to e passed to the execute interface method.
global (Database.QueryLocator | Iterable<sObject>)
start(Database.BatchableContext bc) {}
  1. execute method: this method is called for each batch of records passed to the method. This method takes the following:
·         A reference to the Database.BatchableContext object.
·         A list of sObjects, such as List<sObject>, or a list of parameterized types. If you are using a Database.QueryLocator, the returned list should be used.

Batches of records are not guaranteed to execute in the order they are received from the start method.

   global void execute(Database.BatchableContext BC, list<P>){}

  1. finish method: called after all batches are processed. Use this method to send confirmation emails or execute post-processing operations.

            global void finish(Database.BatchableContext BC){}

To invoke a batch class, instantiate it first and then call Database.executeBatch with the instance of your batch class:
BatchClass   myBatchObject = new BatchClass();

Batch classes can be invoked form a trigger, a class or Developer Console.




Example: Apex Batch Apex Class CleanUpRecords

  1. global class CleanUpRecords implements Database.Batchable<sObject> {
  3. global final String query;
  5. global CleanUpRecords(String q) {
  6.     query = q;
  7.     }
  9. global Database.QueryLocator start(Database.BatchableContext BC){
  10.     return Database.getQueryLocator(query);
  11.     }
  13. global void execute(Database.BatchableContext BC,List<sObject> scope){
  14.     // scope variable now has the records received from QueryLocator.
  15.     delete scope;    
  16.     Database.emptyRecycleBin(scope);
  17.     }
  19. global void finish(Database.BatchableContext BC){
  20. AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob WHERE Id =:BC.getJobId()];
  22.     // Send an email to the Apex job's submitter
  23.     // notifying of job completion.
  25.  Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
  26.  String[] toAddresses = new String[] {a.CreatedBy.Email};
  27.  mail.setToAddresses(toAddresses);
  28.  mail.setSubject('Record Clean Up Status: ' + a.Status);
  29.  mail.setPlainTextBody('The batch Apex job processed ' + a.TotalJobItems +' batches with '+ a.NumberOfErrors + ' failures.');
  30. Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
  31.   }
  32. }

To Execute above Batch Apex

  1. String query = 'SELECT Id,CreatedDate FROM Merchandise__c ' +              'WHERE Id NOT IN (SELECT Merchandise__c FROM Line_Item__c)';
  2. CleanUpRecords c = new CleanUpRecords(query);
  3. Database.executeBatch(c);

To Test above Batch Apex

  1. @isTest
  2. private class TestCleanUpBatchClass {
  4. static testmethod void test() {
  5. // The query used by the batch job.
  6. String query = 'SELECT Id,CreatedDate FROM Merchandise__c ' +
  7.                'WHERE Id NOT IN (SELECT Merchandise__c FROM Line_Item__c)';
  9. // Create some test merchandise items to be deleted
  10. // by the batch job (Mock Objects for testing).
  11. Merchandise__c[] ml = new List<Merchandise__c>();
  12. for (Integer i=0;i<10;i++) {
  13. Merchandise__c m = new Merchandise__c(
  14. Name='Merchandise ' + i,
  15. Description__c='Some description',
  16. Price__c=2,
  17. Total_Inventory__c=100);
  18. ml.add(m);
  19. }
  21. insert ml;
  23. Test.startTest();
  24.      CleanUpRecords c = new CleanUpRecords(query);
  25.      Database.executeBatch(c);
  26. Test.stopTest();
  28. // Verify merchandise items got deleted
  29. Integer i = [SELECT COUNT() FROM Merchandise__c];
  30. System.assertEquals(i, 0);
  32. }
  33. }

Database.query() Vs Database.getQueryLocator

We can retrieve up to 50,000 records.
We can retrieve up to 10,000 records.
If VF page doesn’t have read only attribute, use Database.query().
If VF page have read only attribute, use Database.getQueryLocator().
In Batch Apex, Database.query() supports 50,000 records only.
In Batch Apex, Database.getQueryLocator() supports upto 50 million records.
Returns Iterable<sObject>
Returns Database.QueryLocator
Creates a dynamic SOQL query at runtime.
Creates a QueryLocator object used in batch Apex or Visualforce.

database.query( ) allows you to make a dynamic SOQL query at runtime. You can build up a string and then use that as a query string at run time in the database.query statement to make a SOQL call that is determined at run time.


Popular Posts