场景描述:UAT过后,我们需要将客户的历史数据导进生产环境,由于记录体量很大,通常会先关闭部分Trigger,Process Builder,Workflow等来保证数据能成功导入,事后,为了保证业务数据的合理性,我们会使用Batch来更新那些被禁用后的逻辑。
Template Code:
Batch class:
global class ExampleBatchClass implements Database.Batchable<sObject>{ global ExampleBatchClass(){ // Batch Constructor } // Start Method global Database.QueryLocator start(Database.BatchableContext BC){ return Database.getQueryLocator(query); } // Execute Logic global void execute(Database.BatchableContext BC, List<sObject>scope){ // Logic to be Executed batch wise } global void finish(Database.BatchableContext BC){ // Logic to be Executed at finish } }
ExampleBatchClass b = new ExampleBatchClass(); //Parameters of ExecuteBatch(context,BatchSize) database.executebatch(b,10);
Note: if batch size is not mentioned it is 200 by default.
Sample:将Org中所有Lead历史数据的Status更新为Closed
Code Snap:
global class LeadProcessor implements Database.Batchable<sObject>, Database.Stateful { // instance member to retain state across transactions global Integer recordsProcessed = 0; global Database.QueryLocator start(Database.BatchableContext bc) { // collect the batches of records or objects to be passed to execute String str = 'select Id, Status from Lead'; return Database.getQueryLocator(str); } global void execute(Database.BatchableContext bc, List<Lead> records){ // process each batch of records List<Lead> ldList = new List<Lead>(); for(Lead l : records) { l.Status = 'Closed'; ldList.add(l); recordsProcessed ++; } update ldList; } global void finish(Database.BatchableContext bc){ // execute any post-processing operations System.debug(recordsProcessed + ' records processed.'); AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob WHERE Id = :bc.getJobId()]; } }Test Code:
@isTest private class LeadProcessorTest { @testSetup static void setup() { List<Lead> ldList = new List<Lead>(); for(Integer i = 0; i < 200; i++) { ldList.add(new Lead(LastName = 'Lead' + i, Company = 'com' + i, Status = 'Open')); } insert ldList; } static testMethod void test1() { Test.startTest(); LeadProcessor lp = new LeadProcessor(); Id batchId = Database.executeBatch(lp); Test.stopTest(); } }在Developer Console的Open Excute Anonymous Window执行以下代码:
LeadProcessor leadBach = new LeadProcessor(); Id batchId = Database.executeBatch(leadBach, 100);参考资料:
https://trailhead.salesforce.com/modules/asynchronous_apex/units/async_apex_batch
补充:
Batch特性:如果我们在start里面写查询语句,如果查询中包含关系字段(除关系ID外),那么debug时是出不来关系字段的值的,这时候如果用公式字段代替关系字段,同样debug不出值;如果我们在excute里面做查询,那么debug出来的只有ID和Name的值,其他字段值也出不来。
举例:我们需要处理Account和Contact,在start里面查询语句为:select id, name, accountid, account.site from contact,那么只能debug出id, name, accountid的值;如果我们在excute里面写入:select id, name, site from account,只能debug出id和name的值。
建议:如果是跨对象的过滤,首先将子对象记录在start中查处来(Id),然后在excute里面将查出来的id作为参数传入外部异步方法,该方法主要用来使用select再次查询,这个时候就可以debug出关系字段了,意思是就可以做过滤了。
参考文档:http://www.iterativelogic.com/developing-custom-apex-rollup-summary-field-logic/