[SalesForce] How to combine multiple batches doing same operation on different objects into Single Batch

Every Month, we have to reset a flag(of type boolean) on Custom Objects A,B and C. For this, I have written one batch class per object.

ObjAResetBatch.cls

 public class ObjAResetBatch implements Database.Batchable<SObject> {

    public Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator('SELECT Id,Flag__c FROM A__c WHERE Flag__c = TRUE');
    }

    public void execute(Database.BatchableContext BC, List<SObject> scope){
        List<A__c> objAList = (List<A__c>)scope;
        for(A__c aObj: objAList){
            aObj.Flag__c = FALSE;
        }
        update objAList;        
    }

    public void finish(Database.BatchableContext BC){
    }
}

There are two other batch classes that are almost same as above but work on Custom Objects B & C.

Is it possible to combine these three batches into single batch?

Best Answer

I would think you can utilize something by introducing a constructor to accept the query and accordingly execute it.

Your common batch class will then look like:

public class ObjResetBatch implements Database.Batchable<SObject> {
    private String query;
    private String sObjectType;

    public ObjResetBatch() {
        ... // default constructor
    }

    public ObjResetBatch(String query, String sObjectType) {
        this.query = query;
        this.sObjectType = sObjectType;
    }

    public Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(this.query);
    }

    public void execute(Database.BatchableContext BC, List<SObject> scope){
        if(this.sObjectType == 'A__c') {
            List<A__c> objAList = (List<A__c>)scope;
            for(A__c aObj: objAList){
                aObj.Flag__c = FALSE;
            }
            update objAList;        
        }

        if(this.sObjectType == 'B__c') {
            // do this
        }

        if(this.sObjectType == 'C__c') {
            // do this
        }

    }
}

And then, you execute the batches accordingly:

Database.executeBatch(new ObjResetBatch('SELECT ... FROM A__c WHERE ...', 'A__c'), 1);
Database.executeBatch(new ObjResetBatch('SELECT ... FROM B__c WHERE ...', 'B__c'), 1);
Database.executeBatch(new ObjResetBatch('SELECT ... FROM C__c WHERE ...', 'C__c'), 1);

Note that I haven't really gone into the details of effectively writing all conditions, but this should be a step towards what you are trying to achieve.