How to write Batch Class in
Salesforce.com Apex
In order for us to write batch classes in apex, let us 1st understand what is batch class , when and where it should be used? This is an extensive blog going into details.
Main sections of this post are
1.
What is batch Apex
2.
When to use batch apex
3.
Advantages of using batch apex
4.
Batch Apex Governor limits
5.
Sample Code
What is Batch Apex ?
Batch as the name suggests, is used
when a large data (bulk) volume is involved and it has to be redundantly
processed using a particular logic.
The Batch apex, can be used to conveniently perform time to time task and some real complex job ranging from data cleansing, archiving the data to the other quality improvements.
The Batch apex, can be used to conveniently perform time to time task and some real complex job ranging from data cleansing, archiving the data to the other quality improvements.
When to use Batch Apex?
The typical use of batch apex is
when you want to do a bulk job, but if you do it in a regular apex you’re bound
to hit the governor limits. Batch Classes process the set of records you pass
to it in batches of maximum 200 per batch.
Advantages of using Batch Apex?
Higher Governor Limits
Can be used to process in batches
Work around to other governor limits e.g. Send More than 10
E-mails blog by Ankit Arora
here is the governor limit difference in using batch
here is the governor limit difference in using batch
Area
|
Normal
Context
|
Batch
Context
|
SOQL queries
|
100 SOQL per cycle
|
200 SOQL per cycle
|
records retrieved by SOQL queries
|
50,000
|
50,000,000 (getQueryLocator)
|
executed code statements
|
200,000
|
1,000,000
|
Heap size
|
6 MB
|
12 MB
|
Batch Apex Governor Limits
These are the governor Limits you
need to keep in mind when dealing with Batch Apex
·
Up to five queued or active batch jobs are allowed for Apex.
·
A user can have up to 50 query cursors open at a time. For example, if 50 cursors
are open and a client application still logged in as the same user attempts to
open a new one, the oldest of the 50 cursors is released. Note that this limit
is different for the batch Apex start method, which can have up to
five query cursors open at a time per user. The other batch Apex methods have
the higher limit of 50 cursors. Cursor limits for
different Force.com features are tracked separately. For
example, you can have 50 Apex query cursors, 50 batch cursors, and 50 Visual
force cursors open at the same time.
·
A maximum of 50 million records can
be returned in the Database.QueryLocator object. If more than 50
million records are returned, the batch job is immediately terminated and
marked as Failed.
·
If the start method
returns a QueryLocator, the optional scope parameter ofDatabase.executeBatch can
have a maximum value of 2,000. If set to a higher
value, Salesforce chunks the records returned by the QueryLocator into smaller
batches of up to 2,000 records. If the start method returns an
iterable, the scope parameter value has no upper limit; however, if you use a
very high number, you may run into other limits.
·
If no size is specified with the
optional scope parameter of Database.executeBatch,
Salesforce chunks the records returned by the start method into
batches of 200, and then passes each batch to
the execute method. Apex governor limits are reset for each execution
of execute.
·
The start, execute,
and finish methods can implement up to 10 callouts each.
·
Batch executions are limited to 10
callouts per method execution.
·
The maximum number of batch
executions is 250,000 per 24 hours.
·
Only one batch Apex job's start method can run at a time in an organization. Batch jobs
that haven’t started yet remain in the queue until they're started. Note that
this limit doesn't cause any batch job to fail
and execute methods of batch Apex jobs still run in parallel if more
than one job is running.
Sample Code
Batch Class :
1: global class ExampleBatchClass implements
Database.Batchable<sObject>{
2:
3: global ExampleBatchClass(){
4: // Batch Constructor
5: }
6:
7: // Start Method
8: global Database.QueryLocator
start(Database.BatchableContext BC){
9: return
Database.getQueryLocator(query);
10: }
11:
12: // Execute Logic
13: global void
execute(Database.BatchableContext BC, List<sObject> scope){
14: // Logic to be Executed batch
wise
15:
16: }
17:
18: global void
finish(Database.BatchableContext BC){
19: // Logic to be Executed at finish
20: }
21: }
Call the Batch Class :
1: ExampleBatchClass b = new
ExampleBatchClass();
2: //Parameters of
ExecuteBatch(context,BatchSize)
3: database.executebatch(b,10);
Note : if batch size is not mentioned it is 200 by default.
That’s about it for this post, if you still want a deep dive into Batch Classes I suggest you read this
Do let me know your thoughts Happy Coding !
How
to use Batch Apex in Salesforce
Batch
Apex in Salesforce
As
you all might know about the Salesforce governer limits on its data. When you
want to fetch thousands of records or fire DML on thousands of rows on objects
it is very complex in salesforce and it does not allow you to operate on
more than certain number of records which satisfies the Governer limits.
But
for medium to large enterprises, it is essential to manage thousands of records
every day. Adding/editing/deleting them when needed.
Salesforce
has come up with a powerful concept called Batch Apex. Batch Apex allows you to
handle more number of records and manipulate them by using a specific syntax.
We
have to create an global apex class which extendsDatabase.Batchable Interface because of which the
salesforce compiler will know, this class incorporates batch jobs. Below is a sample class which is
designed to delete all the records of Account object (Lets say your
organization contains more than 50 thousand records and you want to mass delete
all of them).
- global class deleteAccounts implements Database.Batchable
- {
- global final String Query;
- global deleteAccounts(String q)
- {
- Query=q;
- }
-
- global Database.QueryLocator start(Database.BatchableContext BC)
- {
- return Database.getQueryLocator(query);
- }
-
- global void execute(Database.BatchableContext BC,List scope)
- {
- List <Account> lstAccount = new list<Account>();
- for(Sobject s : scope)
- {
- Account a = (Account)s;
- lstAccount.add(a);
- }
- Delete lstAccount;
- }
-
- global void finish(Database.BatchableContext BC)
- {
- //Send an email to the User after your batch completes
- Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
- String[] toAddresses = new String[] {‘sforce2009@gmail.com’};
- mail.setToAddresses(toAddresses);
- mail.setSubject('Apex Batch Job is done‘);
- mail.setPlainTextBody('The batch Apex job processed ');
- Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
- }
- }
///////////////////This is how the batch class is called
- id batchinstanceid = database.executeBatch(new deleteAccounts(‘select Id from Account’));
When
you instantiate the global class and called it using database.executeBatch, the process gets started.
As you have observed the deleteAccounts class accepts your query as a parameter
in the constructor and sets it to the string variable called Query.
The
start method of deleteAccount class which extends database.batchable interface
sets the current query to execute using the Database.getQueryLocator method.
Then
the result of the query can be captured in execute method. The scope list of
SObjects returned as the result of your query.
When
you are executing your batch with a query which returns thousands of records,
the batch will be executed with 200 records each time that is salesforce
divides the total number of records in to batches. Each batch contains 200
records by default (though this is configurable less than 200 by just
introducing the number when you are calling the batch class like database.executebatch(new
deleteAccounts(‘your query’), number here);).
After
processing each batch, the governor limits are reset.
Once
the whole batch of thousands records are done the Finish method gets called and
an email will be sent to the specified person.
==========================================
Calling
one batch class in another batch class
=====================================================
global
class batchApexClass implements Database.Batchable<sObject>{
global final String query;
public batchApexClass(){
query='select name from Studant__c';
}
// this method retrive all the records from
specified object
global
Database.QueryLocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext
BC,List<Studant__c> scope){
List<Studant__c> li=new List<Studant__c>();
for(sObject s:scope){
Studant__c std=(Studant__c)s;
std.name='sunil';
li.add(std);
}
update li;
}
global void finish(Database.BatchableContext
BC){
//Send an email to the User after
your batch completes
Messaging.SingleEmailMessage
mail = new Messaging.SingleEmailMessage();
String[]
toAddresses = new String[] {'practice.sfdc@gmail.com'};
mail.setToAddresses(toAddresses);
mail.setSubject('Apex
Batch Job is done');
mail.setPlainTextBody('oyeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
');
Messaging.sendEmail(new
Messaging.SingleEmailMessage[] { mail });
}
}
USING QUERY LOCATOR
global
class batchApexClass implements Database.Batchable<sObject>{
global final String query;
public batchApexClass(){
query='select name from Studant__c ';
}
// this method retrive all the records from
specified object
global
Database.QueryLocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext
BC,List<Studant__c> scope){
List<Studant__c> li=new
List<Studant__c>();
for(sObject s:scope){
Studant__c std=(Studant__c)s;
std.name='student update';
li.add(std);
}
update li;
}
global void finish(Database.BatchableContext
BC){
//Send an email to the User after
your batch completes
/* Messaging.SingleEmailMessage mail = new
Messaging.SingleEmailMessage();
String[]
toAddresses = new String[] {'practice.sfdc@gmail.com'};
mail.setToAddresses(toAddresses);
mail.setSubject('Apex
Batch Job is done');
mail.setPlainTextBody('oyeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
');
Messaging.sendEmail(new
Messaging.SingleEmailMessage[] { mail });*/
database.executeBatch(new batchApexClass1 ());
}
}
=========================================
Developer
console code
=========================================
id
batchinstanceid = database.executeBatch(new batchApexClass ());/*this is to
execute batchapex for update*/
/*List<Studant__c>
li=[select id from studant__c ];
delete li;*/
global class
scheduleExampleBatchClass implements Schedulable
{
global void execute(SchedulableContext ctx)
{
ExampleBatchClass ebs = new ExampleBatchClass();
}
}
{
global void execute(SchedulableContext ctx)
{
ExampleBatchClass ebs = new ExampleBatchClass();
}
}
================================
developer
console
System.schedule('Job2', '59 * * * * ?', new
scheduleExampleBatchClass());
USING ITERABLE
global class ExampleBatchClass implements
Database.Batchable<batch__c>
{
global Iterable<batch__c> start(Database.BatchableContext BC)
{
list<Batch__c> b = [select name,id from batch__c];
return b;
}
global void execute(Database.BatchableContext BC, List<batch__c> bat)
{
for(Batch__c b : bat)
b.name = 'All Idiots';
update bat;
}
global void finish(Database.BatchableContext BC)
{
System.debug('Success');
}
}
{
global Iterable<batch__c> start(Database.BatchableContext BC)
{
list<Batch__c> b = [select name,id from batch__c];
return b;
}
global void execute(Database.BatchableContext BC, List<batch__c> bat)
{
for(Batch__c b : bat)
b.name = 'All Idiots';
update bat;
}
global void finish(Database.BatchableContext BC)
{
System.debug('Success');
}
}
No comments:
Post a Comment