Prelude
I understand the following regarding batch Apex:
State | Variable Values |
---|---|
stateful | static are reset for each batch execute() run |
instance (non-static) are maintained across all batch execute() runs |
|
non-stateful | static are reset for each batch execute() run |
instance (non-static) are reset for each batch execute() run |
As I understand it, each batch execute()
run is considered a separate transaction.
Background
In an inherited org, I just ran across a non-stateful batch class, which within the execute()
method references a static
variable in a separate non-Batchable
class.
Simplified Example
Separate Class
public class SeparateClass {
public static Set<Id> staticSetIds = new Set<Id>();
}
Batch Class
public class NonStatefulBatch implements Database.Batchable<sObject> {
public Database.QueryLocator start(Database.BatchableContext BC) {
// build query
return Database.getQueryLocator(query);
}
public void execute(Database.BatchableContext BC, List<Account> scope) {
// Work
for (Account acc : scope) {
if (!SeparateClass.staticSetIds.contains(acc.Id) {
// More work
SeparateClass.staticSetIds.add(acc.Id);
}
// Even more work
}
public void finish(Database.BatchableContext BC) {
System.debug('Finished');
}
}
Comments
This separate class' static
variable is also used in other contexts, such as triggers, where -- if I understand correctly -- it will do what I think they want it to do as all "batches" of a trigger run are considered the same transaction: This variable will maintain value for the full run of the trigger.
I think the original code writer was expecting/hoping that the same thing would happen in this batch class.
Questions
- Is my assumption that each batch
execute()
run is a separate transaction, thus this separate class'static
variable value will not be maintained for the full run of the batches? - Would it act differently if this batch class were
Stateful
?
UPDATE 1
Minutes after posting the original question
I posted this too soon, maybe. After further analysis I see that the batch updates Accounts, and the SeparateClass.staticSetIds
is referenced in the before update
of the Account trigger handler. I haven't looked at the 1
s and 0
s yet, but maybe that is why it is used in this batch.
SeparateClass
is not referenced by the object graph tied to any instance variable. One possible solution: based on the state of your (stateful)Batchable
. you construct theSeparateClass
and initialize it with whatever state it needs. Another solution: have the state in yourBatchable
includeSeparateClass
(via an instance variable) and update it as needed throughout the runs. While this solution might appear cleaner, serialization issues could bite.execute
.