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
SFDC Coder 8SFDC Coder 8 

Batch apex for 2 objects

Hi All,
I have written batch apex to insert data in Task from two objects.
I am able to get data from Obj1__c. I am not able to get from Obj2__c
Here is my code.
 
global class batchTwo Implements Schedulable, Database.Batchable<sObject>{
global void execute(SchedulableContext sc) {
    Database.executeBatch(this);
}

global database.queryLocator start(Database.BatchableContext BC) {
    
    
        return database.getQueryLocator([SELECT Id,AccountId__c,F1__c,F2__c FROM Obj1__c]);
    
} 

global void execute(Database.BatchableContext BC, list <obj1__c> scope) {

    List <Task> taskList = new List<Task>();

   Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>([SELECT Account_Name__r.Id,Obj2_F2__c FROM Obj2__c]);
    
    for(Obj1__c c : scope) {
            Task tsk             = new Task();
            if(mapObj2.containsKey(c.AccountId__c)) {
             Obj2__c tmpSales = mapObj2.get(c.AccountId__c);
            
             tsk.F1__c=tmpSales.Obj2_F2__c;
             
            }
            
            tsk.WhatId           = c.AccountId__c;
            tsk.ActivityDate     = System.today();
            tsk.Status           = 'Open';
            tsk.Priority         = 'Normal';
            tsk.Subject          = 'call';
            tsk.P1__c=c.F1__c;
            tsk.P2__c=c.F2__c;
            
           taskList.add(tsk);
    } //close for-loop

   
        insert taskList;
    
       
    
} 

global void finish(Database.BatchableContext BC) {


} 
}

I am getting problem in Line no. 21 to 24.
Please suggest me what changes need to be done.
Please help me.
Thanks in Advance
Best Answer chosen by SFDC Coder 8
karthikeyan perumalkarthikeyan perumal
Hello, 

use below updated code. 

i modified this line of code 

Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>([SELECT Account_Name__r.Id,Obj2_F2__c FROMObj2__c]);

to 

Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>();
for(Obj2__c obj2 : [SELECT Account_Name__r.Id,Obj2_F2__c FROM Obj2__c])
myMap.put(obj2.Id, obj2);
 
global class batchTwo Implements Schedulable, Database.Batchable<sObject>{
global void execute(SchedulableContext sc) {
    Database.executeBatch(this);
}

global database.queryLocator start(Database.BatchableContext BC) {
    
    
        return database.getQueryLocator([SELECT Id,AccountId__c,F1__c,F2__c FROM Obj1__c]);
    
} 

global void execute(Database.BatchableContext BC, list <obj1__c> scope) {

    List <Task> taskList = new List<Task>();

   Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>();
   
   for(Obj2__c obj2 : [SELECT Account_Name__r.Id,Obj2_F2__c FROM Obj2__c])
{
        myMap.put(obj2.Id, obj2);
}
    
    for(Obj1__c c : scope) {
            Task tsk             = new Task();
            if(mapObj2.containsKey(c.AccountId__c)) {
             Obj2__c tmpSales = mapObj2.get(c.AccountId__c);
            
             tsk.F1__c=tmpSales.Obj2_F2__c;
             
            }
            
            tsk.WhatId           = c.AccountId__c;
            tsk.ActivityDate     = System.today();
            tsk.Status           = 'Open';
            tsk.Priority         = 'Normal';
            tsk.Subject          = 'call';
            tsk.P1__c=c.F1__c;
            tsk.P2__c=c.F2__c;
            
           taskList.add(tsk);
    } //close for-loop

   
        insert taskList;
    
       
    
} 

global void finish(Database.BatchableContext BC) {


} 
}

Hope this will help you, 

Mark best Answer if its works for you. 

Thanks
karthik
 

All Answers

Jamal RidaJamal Rida
Hi,

I suggest to add a debug before line 21 to check if the  Map<Id, Obj2__c> mapObj2 returns something, because for me it seems like there are no records in this sObject. One more thing i don't see why you need to query for all records on Obj2__c everytime ? it is better to loop through the scope get the accountId and then fetch only Obj2__c that has this AccountId at least you have only the accurate records, Or create class variable where you store all records and then use it witohut having to query everytime for it.

 
karthikeyan perumalkarthikeyan perumal
Hello, 

use below updated code. 

i modified this line of code 

Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>([SELECT Account_Name__r.Id,Obj2_F2__c FROMObj2__c]);

to 

Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>();
for(Obj2__c obj2 : [SELECT Account_Name__r.Id,Obj2_F2__c FROM Obj2__c])
myMap.put(obj2.Id, obj2);
 
global class batchTwo Implements Schedulable, Database.Batchable<sObject>{
global void execute(SchedulableContext sc) {
    Database.executeBatch(this);
}

global database.queryLocator start(Database.BatchableContext BC) {
    
    
        return database.getQueryLocator([SELECT Id,AccountId__c,F1__c,F2__c FROM Obj1__c]);
    
} 

global void execute(Database.BatchableContext BC, list <obj1__c> scope) {

    List <Task> taskList = new List<Task>();

   Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>();
   
   for(Obj2__c obj2 : [SELECT Account_Name__r.Id,Obj2_F2__c FROM Obj2__c])
{
        myMap.put(obj2.Id, obj2);
}
    
    for(Obj1__c c : scope) {
            Task tsk             = new Task();
            if(mapObj2.containsKey(c.AccountId__c)) {
             Obj2__c tmpSales = mapObj2.get(c.AccountId__c);
            
             tsk.F1__c=tmpSales.Obj2_F2__c;
             
            }
            
            tsk.WhatId           = c.AccountId__c;
            tsk.ActivityDate     = System.today();
            tsk.Status           = 'Open';
            tsk.Priority         = 'Normal';
            tsk.Subject          = 'call';
            tsk.P1__c=c.F1__c;
            tsk.P2__c=c.F2__c;
            
           taskList.add(tsk);
    } //close for-loop

   
        insert taskList;
    
       
    
} 

global void finish(Database.BatchableContext BC) {


} 
}

Hope this will help you, 

Mark best Answer if its works for you. 

Thanks
karthik
 
This was selected as the best answer
SFDC Coder 8SFDC Coder 8
Hi Kartthikeyan,
Now, I am comparing one more filed value like

Map<Id, Obj2__c> mapObj2=new Map<Id, Obj2__c>(); for(Obj2__c obj2 : [SELECT Account_Name__r.Id,Obj2_F2__c,F3__r.Id FROM Obj2__c]) { myMap.put(obj2.Id, obj2); }

if(mapObj2.containsKey(c.AccountId__c) && mapObj2.F3__r.Id==c.F3__r.Id) {
Obj2__c tmpSales = mapObj2.get(c.AccountId__c);
tsk.F1__c=tmpSales.Obj2_F2__c; }

When I made changes like this I am getting following error in if loop

Initial term of field expression must be a concrete SObject:

What change I need to do?
karthikeyan perumalkarthikeyan perumal
Hello,

first Change this  line of  "  myMap.put(obj2.Id, obj2) "  to 

like below.

mapObj2.put(obj2.Id, obj2);

now its work.  other wise follow below steps. 


i recommend you to put system debug befor this line   " for(Obj1__c c : scope) { " 

System.Debug(mapObj2.id);

System.Debug(mapObj2.Obj2__c);

let see what it will contain. 

then try to retrive the values as accordingly.

Thanks
karthik
 
Soufiyane IbrizSoufiyane Ibriz
Hello can anyone help me please to create this batch need to implement