salesforce batch apex

在salesforce中,想要实现批处理,可以使用salesforce提供的Database.Batchable接口。

Batch apex

batch apex也是一个apex,只是继承了Database.Batchable接口。

public class SearchAndReplace implements Database.Batchable<sObject>{
 public Database.QueryLocator start(Database.BatchableContext bc){
      return Database.getQueryLocator(query);
   }
  public void execute(Database.BatchableContext bc, List<sObject> scope){
     for(sobject s : scope){
         s.put(Field,Value); 
     }
     update scope;
   }
  public void finish(Database.BatchableContext bc){
   }
}
  • batch apex 必须被定义为public或global类。 

里面有三个必要的方法:start、execute、finish。

1.start

public Database.QueryLocator start(Database.BatchableContext bc){
      String query = 'SELECT Id FROM Account LIMIT 20';
      return Database.getQueryLocator(query);
   }

start方法在批处理开始时调用,将查询到的结果传给execute方法。

  • 使用 QueryLocator 对象,会绕过 SOQL 查询检索的记录总数的限制。
  • 每执行一次batch跑一次start方法。
  • Database.QueryLocator 对象中最多可以返回 5000 万条记录。 如果返回的记录超过 5000 万条,则批处理作业将立即终止并标记为“Failed”。
  • 在start中执行的soql最好不要使用子查询。在excute中而不是在start中使用子查询可以提高执行速度。

2.execute

   public void execute(Database.BatchableContext bc, List<Account> scope){
     for(Account acc : scope){
       acc.Name = 'test';
     }
     update scope;
    }

对于传进来的每批记录,都会执行 execute方法。

  • execute处理从start中传进来的数据时,处理的顺序不能保证。
  • 如果执行一次batch处理1000条数据,batch size是200,那么跑5次execute方法,也就是5个事务,每个事务中处理200条数据。如果第一个事务成功,第二个事务失败,那么第一个事务中对数据的更新不会回滚。
  • salesforce推荐在excute中重新查询该事务中处理的数据,并使用FOR UPDATE将数据锁定,避免更新冲突。重新查询只需要ID即可。
Account [] accts = [SELECT Id FROM Account LIMIT 2 FOR UPDATE];

3.finish

public void finish(Database.BatchableContext bc){
   AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,
      TotalJobItems, CreatedBy.Email 
      FROM AsyncApexJob WHERE Id = :bc.getJobId()];
   Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
   String[] toAddresses = new String[] {a.CreatedBy.Email};
   mail.setToAddresses(toAddresses);
   mail.setSubject('Apex Sharing Recalculation ' + a.Status);
   mail.setPlainTextBody('The batch Apex job processed ' + a.TotalJobItems +
   ' batches with '+ a.NumberOfErrors + ' failures.');
   Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}

finish方法在所有批次数据都处理完毕后调用,可用于发邮件等操作,也可以是空的。

  • 也可以在finish中执行另外一个新的batch。
  • 每执行一次batch跑一次finish方法。
执行batch

1.使用Database.executeBatch来提交batch job。

Database.executeBatch需要包含两个参数,一个是要执行的batch,另一个是batch size。batch size不传默认是200,最大值是2000。返回值是AsyncApexJob表的ID。

Id batchInstanceId = Database.executeBatch(new UpdateAccountFields(), 5);
AsyncApexJob aaj = [SELECT Id, Status, JobItemsProcessed, TotalJobItems,NumberOfErrors 
                    FROM AsyncApexJob WHERE ID =: batchInstanceId ];
  • 当我们调用Database.executeBatch来执行batch时,salesforce会把程序挂到队列上排队,实际执行可能会延迟。

2.使用 System.scheduleBatch 方法安排批处理作业在将来的某个时间运行一次。

System.scheduleBatch有4个参数。第一个是要执行的batch,第二个是job name,第三个是多少分钟后执行,第4个是batch size。不传默认是200,最大是2000。返回值是CronTrigger表的ID。

String cronID = System.scheduleBatch(new UpdateAccountFields(), 'jobName', 60, 5);

CronTrigger ct = [SELECT Id, TimesTriggered, NextFireTime
                FROM CronTrigger WHERE Id = :cronID];
Database.Stateful

batch的每个事务之间是不能互相通信的,使用Database.Stateful使变量在事务之间保留其值。静态变量不保留其值,并在事务之间重置。该功能常用于计数、汇总等。

public class SummarizeAccountTotal implements 
    Database.Batchable<sObject>, Database.Stateful{

   public final String Query;
   public integer Summary;
  
   public SummarizeAccountTotal(String q){
     Query=q;
     Summary = 0;  
   }

   public Database.QueryLocator start(Database.BatchableContext bc){
      return Database.getQueryLocator(query);
   }
   
   public void execute(Database.BatchableContext bc, List<sObject> scope){
      for(sObject s : scope){
         Summary = Integer.valueOf(s.get('total__c'))+Summary;
      }
   }

   public void finish(Database.BatchableContext bc){
   }
}
Batch apex的测试

关于batch apex的test class也有一些需要注意的

  • 在test class里只能跑一次excute方法,也就是说,如果batch size是200,有201条数据,test class会报错。
  • 因为executeBatch是异步方法,所以要确保在执行之后再判断执行的结果,把executeBatch写在startTest和stopTest之间。
   Test.StartTest();
   OwnerReassignment reassign = new OwnerReassignment();
   ID batchprocessid = Database.executeBatch(reassign);
   Test.StopTest();

参照:Salesforce Developers 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值