function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Daniel B ProbertDaniel B Probert 

dynamic soql query in apex batch

Hi All,

I've recenrtly started working with some batch apex and have generally found it pretty simple to deal with but have now hit a problem that I can't get round.

Setup:

One object Entitlement__c which I need to provide a button to force update records that match a criteria.
I've create a second object Entitlement_Updates__c which allows them to set the criteria Year__c, Term__c

I then have a custom VF page that based on their criteria tells them how many records match and if the number is greater than 0 they get a button to press that is supposed to invoke a batch apex - all of this I've managed to get working relatively easily.

my problem is that I am unable to pass my soql query from my apex class to my batch apex.

Apex Class: 

public with sharing class FPS_ManualIntervention {
    public FPS_Update__c FPS { get; set; }
     // Class Constructor
    public FPS_ManualIntervention(ApexPages.StandardController controller){
        FPS =  (FPS_Update__c)controller.getRecord();  
      }
    // button page for firing of apex batch class
    public PageReference updaterecords() {
        string fpyear = fps.year__c;
        string fpterm = fps.term__c;
        string fpcountry = fps.country__c;
        string fpstudenttype = fps.student_type__c;
        Database.executeBatch(new BatchEntitlementUpdate('SELECT ID, Year__c, Term__c, StudentType__c, Student__r.Country__c ' +
                ' FROM Entitlement__c ' +
                ' WHERE Year__c =:\'' + fpyear + '\'' +
                ' AND Term__c =:\'' + fpterm + '\'' +
                ' AND StudentType__c=:\'' + fpstudenttype + '\''+
                ' AND Country__c=:\'' + fpcountry + '\''), 10);
        PageReference redirect  = new PageReference('/apex/FPSManageRunning?id=' + fps.id);
        redirect.setRedirect(true);
        return redirect;
        return null;
    }
 }

the button on this page is then firing this batch apex:

global class BatchEntitlementUpdate implements Database.Batchable<sObject>{

   global final String Query;

   global BatchEntitlementUpdate(String q){
             Query=q;
   }
   global Database.QueryLocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
   }
    global void execute (Database.Batchablecontext BC, list<Entitlement__c> scope){
        List<Entitlement__c> lsttoupdate = new List<Entitlement__c>();
        for(Entitlement__c ent:scope){
            ent.BatchProcess__c = 10;
            lsttoupdate.add(ent);
        }
        update lsttoupdate;
    }
    global void finish(Database.Batchablecontext BC){
    }
}

i've been reading so many docs that i've kind of lost the plot on how this should or could look now so any guidance appreicated.

the code as it is brings back: First error: Only variable references are allowed in dynamic SOQL/SOSL.


Best Answer chosen by Daniel B Probert
Grazitti TeamGrazitti Team
Hi Daniel,

Can you please try this code?

Apex Class:

public with sharing class FPS_ManualIntervention {
    public FPS_Update__c FPS { get; set; }
     // Class Constructor
    public FPS_ManualIntervention(ApexPages.StandardController controller){
        FPS =  (FPS_Update__c)controller.getRecord(); 
      }
    // button page for firing of apex batch class
    public PageReference updaterecords() {
        string fpyear = fps.year__c;
        string fpterm = fps.term__c;
        string fpcountry = fps.country__c;
        string fpstudenttype = fps.student_type__c;
        BatchEntitlementUpdate b = new BatchEntitlementUpdate(fpyear,fpterm,fpcountry,fpstudenttype);
        database.executebatch(b,10);
        PageReference redirect  = new PageReference('/apex/FPSManageRunning?id=' + fps.id);
        redirect.setRedirect(true);
        return redirect;
    }
}

Batch Class:

global class BatchEntitlementUpdate implements Database.Batchable<sObject>{
     Global string fpyear ;
     Global string fpterm ;
     Global string fpcountry ;
     Global string fpstudenttype ;
  
// Batch Constructor
    global BatchEntitlementUpdate(String fpyear,String fpterm,String fpcountry,String fpstudenttype){
        this.fpyear = fpyear;
        this.fpterm = fpterm;
        this.fpcountry = fpcountry;
        this.fpstudenttype = fpstudenttype;
    }
 
   global Database.QueryLocator start(Database.BatchableContext BC){
      String query = 'SELECT ID, Year__c, Term__c, StudentType__c, Student__r.Country__c ' +
                ' FROM Entitlement__c ' +
                ' WHERE Year__c =:\'' + fpyear + '\'' +
                ' AND Term__c =:\'' + fpterm + '\'' +
                ' AND StudentType__c=:\'' + fpstudenttype + '\''+
                ' AND Country__c=:\'' + fpcountry + '\'';
      return Database.getQueryLocator(query);
   }
  
   global void execute (Database.Batchablecontext BC, list<Entitlement__c> scope){
        List<Entitlement__c> lsttoupdate = new List<Entitlement__c>();
        for(Entitlement__c ent:scope){
            ent.BatchProcess__c = 10;
            lsttoupdate.add(ent);
        }
        update lsttoupdate;
    }

    global void finish(Database.Batchablecontext BC){
    }
}

Please mark as best answer if it solves your problem.

Regards,
Grazitti Team
www.grazitti.com

All Answers

Grazitti TeamGrazitti Team
Hi Daniel,

Can you please try this code?

Apex Class:

public with sharing class FPS_ManualIntervention {
    public FPS_Update__c FPS { get; set; }
     // Class Constructor
    public FPS_ManualIntervention(ApexPages.StandardController controller){
        FPS =  (FPS_Update__c)controller.getRecord(); 
      }
    // button page for firing of apex batch class
    public PageReference updaterecords() {
        string fpyear = fps.year__c;
        string fpterm = fps.term__c;
        string fpcountry = fps.country__c;
        string fpstudenttype = fps.student_type__c;
        BatchEntitlementUpdate b = new BatchEntitlementUpdate(fpyear,fpterm,fpcountry,fpstudenttype);
        database.executebatch(b,10);
        PageReference redirect  = new PageReference('/apex/FPSManageRunning?id=' + fps.id);
        redirect.setRedirect(true);
        return redirect;
    }
}

Batch Class:

global class BatchEntitlementUpdate implements Database.Batchable<sObject>{
     Global string fpyear ;
     Global string fpterm ;
     Global string fpcountry ;
     Global string fpstudenttype ;
  
// Batch Constructor
    global BatchEntitlementUpdate(String fpyear,String fpterm,String fpcountry,String fpstudenttype){
        this.fpyear = fpyear;
        this.fpterm = fpterm;
        this.fpcountry = fpcountry;
        this.fpstudenttype = fpstudenttype;
    }
 
   global Database.QueryLocator start(Database.BatchableContext BC){
      String query = 'SELECT ID, Year__c, Term__c, StudentType__c, Student__r.Country__c ' +
                ' FROM Entitlement__c ' +
                ' WHERE Year__c =:\'' + fpyear + '\'' +
                ' AND Term__c =:\'' + fpterm + '\'' +
                ' AND StudentType__c=:\'' + fpstudenttype + '\''+
                ' AND Country__c=:\'' + fpcountry + '\'';
      return Database.getQueryLocator(query);
   }
  
   global void execute (Database.Batchablecontext BC, list<Entitlement__c> scope){
        List<Entitlement__c> lsttoupdate = new List<Entitlement__c>();
        for(Entitlement__c ent:scope){
            ent.BatchProcess__c = 10;
            lsttoupdate.add(ent);
        }
        update lsttoupdate;
    }

    global void finish(Database.Batchablecontext BC){
    }
}

Please mark as best answer if it solves your problem.

Regards,
Grazitti Team
www.grazitti.com
This was selected as the best answer
Daniel B ProbertDaniel B Probert
great thanks that worked perfectly..

just had to swap my working around :)

cheers
dan