All of the sample code so far has used a QueryLocator
object to define the scope of its batch. This enables up to 50 million records to be processed by the batch job, but requires that the scope be defined entirely using a single SOQL statement. This can be too limiting for some batch processing tasks, so the iterable batch scope is offered as an alternative.
The iterable scope allows custom Apex code to determine which records are processed in the batch. For example, you could use an iterable scope to filter the records using criteria that are too complex to be expressed in SOQL. The downside of the iterable approach is that standard SOQL limits apply. This means you can process a maximum of 50,000 records in your batch job, a dramatic reduction from the 50 million record limit of a QueryLocator
object.
To develop a batch with iterable scope, you must first write code to provide data to the batch. There are two parts to this task:
Implement the Iterator interface—The Iterator
is a class for navigating a collection of elements. It navigates in a single direction, from beginning to end. It requires that you implement two methods: hasNext
and next
. The hasNext
method returns true
if additional elements are left to navigate to, false
when the end of the collection has been reached. The next
method returns the next element in the collection. Iterator
classes must be global.
Implement the Iterable interface—Think of this class as a wrapper or locator object that directs the caller to an Iterator
. It requires a single global method to be implemented, called Iterator
, which returns an Iterable
object. Like Iterator
, classes implementing Iterable
must be global.
You could write two separate classes, one to implement each interface. Or you can implement both interfaces in a single class, the approach taken in the code in Listing 9.5.
global class ProjectIterable
implements Iterator<Project__c>, Iterable<Project__c> {
List<Project__c> projects { get; set; }
Integer i;
public ProjectIterable() {
projects = [SELECT Name FROM Project__c ORDER BY Name ];
i = 0;
}
global Boolean hasNext() {
if (i >= projects.size()) {
return false;
} else {
return true;
}
}
global Project__c next() {
i++;
return projects[i-1];
}
global Iterator<Project__c> Iterator() {
return this;
}
}
With the implementation of the Iterable
class ready for use, examine the code in Listing 9.6. It is very similar to the first Batch Apex example. The only notable differences are that the parameterized type has been changed from SObject
to Project__c
, and the start
method now returns the Iterable
class developed in Listing 9.5.
global class Listing9_6
implements Database.Batchable<Project__c> {
global Iterable<Project__c> start(Database.BatchableContext context) {
System.debug('start'),
return new ProjectIterable();
}
global void execute(Database.BatchableContext context,
List<Project__c> scope) {
System.debug('execute'),
for(Project__c rec : scope) {
System.debug('Project: ' + rec.Name);
}
}
global void finish(Database.BatchableContext context) {
System.debug('finish'),
}
}
Turn on the debug log for your user and run the Listing9_6
job. Examine the logs and see for yourself that you’ve accomplished the same work as the Listing9_1
code using an iterable scope instead of a QueryLocator
object.
18.226.251.70