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:
- 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)
{}
- 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>){}
- 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();
Database.executeBatch(myBatchObject);
Batch
classes can be invoked form a trigger, a class or Developer Console.
Example: Apex Batch Apex Class CleanUpRecords
- global class CleanUpRecords
implements Database.Batchable<sObject> {
-
- global final String
query;
-
- global
CleanUpRecords(String q) {
- query = q;
- }
-
- global Database.QueryLocator
start(Database.BatchableContext
BC){
- return Database.getQueryLocator(query);
- }
-
- global void execute(Database.BatchableContext
BC,List<sObject> scope){
- // scope variable now has the records
received from QueryLocator.
- delete scope;
- Database.emptyRecycleBin(scope);
- }
-
- global void finish(Database.BatchableContext
BC){
- AsyncApexJob a = [SELECT Id, Status,
NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob WHERE Id
=:BC.getJobId()];
-
- // Send an email to the Apex job's
submitter
- // notifying of job completion.
-
- Messaging.SingleEmailMessage mail = new
Messaging.SingleEmailMessage();
- String[] toAddresses = new String[]
{a.CreatedBy.Email};
- mail.setToAddresses(toAddresses);
- mail.setSubject('Record Clean Up Status:
' + a.Status);
- mail.setPlainTextBody('The batch Apex job
processed ' + a.TotalJobItems +' batches with '+ a.NumberOfErrors + ' failures.');
- Messaging.sendEmail(new
Messaging.SingleEmailMessage[] { mail });
- }
- }
To Execute above Batch Apex
- String query =
'SELECT Id,CreatedDate FROM Merchandise__c ' + 'WHERE Id NOT IN (SELECT
Merchandise__c FROM Line_Item__c)';
- CleanUpRecords c =
new CleanUpRecords(query);
- Database.executeBatch(c);
To Test above Batch Apex
- @isTest
- private
class TestCleanUpBatchClass {
-
- static testmethod
void test() {
- // The query used by
the batch job.
- String query =
'SELECT Id,CreatedDate FROM Merchandise__c ' +
- 'WHERE Id NOT IN (SELECT
Merchandise__c FROM Line_Item__c)';
-
- // Create some test
merchandise items to be deleted
- // by the batch job
(Mock Objects for testing).
- Merchandise__c[] ml
= new List<Merchandise__c>();
- for (Integer
i=0;i<10;i++) {
- Merchandise__c m =
new Merchandise__c(
- Name='Merchandise '
+ i,
- Description__c='Some
description',
- Price__c=2,
- Total_Inventory__c=100);
- ml.add(m);
- }
-
- insert ml;
-
- Test.startTest();
- CleanUpRecords c = new
CleanUpRecords(query);
- Database.executeBatch(c);
- Test.stopTest();
-
- // Verify
merchandise items got deleted
- Integer i = [SELECT
COUNT() FROM Merchandise__c];
- System.assertEquals(i,
0);
-
- }
- }
Database.query() Vs Database.getQueryLocator
Database.query()
|
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.
|
Comments
Post a Comment