+ Start a Discussion
TiborMTiborM 

How to resolve limit 100 records in bulk operation?

Hi all,

 

i need somehow make bulk operation in apec class for more than 100 records. To make easier to understand i write little example what I need to do. Please don't aske me why I need it - because.

 

 

global class AccountsOpenCases implements Schedulable {
	public static String CRON_EXP = '0 0 8 * * ?';
	
	global void execute(SchedulableContext SC)
	{
		Account[] accs = [SELECT id, name, NO_OF_OPEN_CASES__c from Account];
		for (Account item : accs)
		{
			int i = [SELECT count() from Case where STATUS != 'CLOSE' and status != 'PENDING CLOSE' and status != 'SERVICE REQUEST' and account = :item.id];
			item.NO_OF_OPEN_CASES__c = i;
			update item;
		}
	}
}

 

 

Anand@SAASAnand@SAAS

First of all, why are using "Schedulable" interface if all you want to do is update records. Schedulable interface is when you want to schedule another Apex class to run. It is not a best practice to put your logic in this class. I'd write a class that implements the Batchable interface and call that from your schedulable class below. Batchable interfaces can process a very large number of records.

TiborMTiborM

this is something which I don't know..

 

We need schedulable to run this class every day. I didn't know that something like Batchable interface exists...

 

thank you, i'll try it.

TiborMTiborM

hi,

 

i wrote Batchable class, but now i have problem with scheduling

 

class code:

 

 

global class CriticalAccountNoOfOpenCasesBatch implements Database.Batchable<sObject> {
	global final String query = 'SELECT Id, Name FROM Account';
	
	global Database.QueryLocator start(Database.BatchableContext BC)
	{
		return Database.getQueryLocator(query);
	}
	
	global void execute(Database.BatchableContext BC, List<sObject> scope)
	{
		for (sObject item : scope)
		{
			String id = String.valueOf(item.get('Id')); 
			Integer i = [SELECT count() FROM CASE where AccountId = :id AND (status != 'Closed' OR  status != 'Pending close')];
			item.put('Number_of_open_cases__c', i);
			update item;
		}
	}
	
	global void finish(Database.BatchableContext BC)
	{
		
	}
}

 

Test method:

@isTest
private class CriticalAccountTests {

    static testMethod void NoOfCasesBatchableTest()
    {
		test.starttest();
		CriticalAccountNoOfOpenCasesBatch GetCases = new CriticalAccountNoOfOpenCasesBatch();

GetCases.query =

'SELECT Id, Name FROM Account LIMIT 200'; ID batchprocessid = Database.executeBatch(GetCases, 200); test.stoptest(); } }

 

Schedule Class:

 

 

global public class CriticalAccountNoOfCasesScheduler implements Schedulable {
	public static String CRON_EXP = '0 0 6 * * ?';
	
	global void execute(SchedulableContext SC)
	{
		CriticalAccountNoOfOpenCasesBatch GetCases = new CriticalAccountNoOfOpenCasesBatch();
		ID batchprocessid = Database.executeBatch(GetCases);
		AsyncApexJob aaj = [SELECT Id, Status, JobItemsProcessed, TotalJobItems, NumberOfErrors FROM AsyncApexJob WHERE ID =: batchprocessid ];
	}
}

 

 

When I shcedule it and look into SETUP -> MONITORING -> APEX JOBS i saw than it have 15 FAILURES.

 

ActionSubmitted DateJob TypeStatusTotal BatchesBatches ProcessedFailuresSubmitted ByCompletion DateApex ClassApex MethodApex Job ID
 28.5.2010 12:00Batch ApexCompleted161615ZOOM Support28.5.2010 12:00CriticalAccountNoOfOpenCasesBatch 70730000001QPZb

 

Why it fail? How can I debug it?

 

 

How can I run this batch in some debug mode or how is possible to run classes by press some button or wahtever and see results??

 

 

Anand@SAASAnand@SAAS

My guess for why it failed is because you have a SOQL  and an update inside a for loop and you will hit governor limits in doing so.  Here's a rough idea of how you would go about changing the execute method.

Map<Id,Integer> accCaseCount = new Map<Id,Integer>();
//Use the new GROUP BY clause to AccountId  and get the count
//Store the counts in the above map.
Integer openCaseCount=0;
List<Case> casesToUpdt = new List<Case>();
for (sObject item : scope)
{
String id = String.valueOf(item.get('Id')); 
openCaseCount=accCaseCount.get(item.get('AccountId'));
item.put('Number_of_open_cases__c', openCaseCount);
casesToUpdt.add(item);
}
update casesToUpdt;

Please refer to the following link on "bulkifying" your trigger/apex code:

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_patterns_bulk.htm

 

Apex now allows you to do "Select ...group by". for more information on that please refer to:

http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_soql_select.htm