015_异步处理_Batch Apex

先理解一下定义:

所谓异步,是指在进行输入输出处理时,不必等到输入输出处理完毕才返回。所以异步的同义语是非阻塞(None Blocking)。

举个例子:普通B/S模式(同步)AJAX技术(异步)
同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事
异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕

同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。


所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法。

以通讯为例
同步:发送一个请求,等待返回,然后再发送下一个请求
异步:发送一个请求,不等待返回,随时可以再发送下一个请求 ;在CPU空闲时候 执行。
并发:同时发送多个请求

 

salesforce本身对于很多数据操作的次数均有严格的限制:

Number of SOQL queries: 100                             -->一次执行SOQL的次数不能超过100次
Number of query rows: 50000                             -->一次查出的数据行数不能超过50000条
Number of SOSL queries: 20                               -->一次执行SOSL次数不能超过20次
Number of DML statements: 150                         -->DML语句不能超过150条
Number of DML rows: 10000                               -->一次操作数据行数不能超过10000行
Maximum CPU time: 10000                                 -->最大的CPU时间不能超过10000ms
Maximum heap size: 6000000                             -->堆大小不能超过6000000B
Number of callouts:100                                       -->一次执行callouts次数不能超过100次
Number of Email Invocations: 10                          -->Email调用次数不能超过10次
Number of future calls: 50                                   -->调用Future次数不能超过50次
Number of queueable jobs added to the queue:50  -->添加到队列的queueable job数量不能超过50次
Number of Mobile Apex push calls: 10                   -->移动端Apex push调用最多不能超过10次

所以,在我们想处理大批量数据的时候,或者是担心CPU 超时,就要考虑使用异步处理了;

Salesforce 异步处理包括几种类型:

Future方法:在自己线程中运行,直到资源可用才运行 用于Web service callout.
Batch Apex:运行大量的Job,数量超过正常处理限制 用于数据DML操作
QueueableApex:和Future类似,但是提供额外的工作链,允许完成更复杂的类型 用于执行顺序处理操作与外部Web服务。
ScheduledApex:指定时间运行apex 固定时间的任务,例如每日或每周等任务

数据批处理Batchable

start()用于查询数据,并将查询数据封装到List中
用于收集要传递给接口方法的记录或对象执行进行处理。此方法在Batch Apex作业开始时调用一次,并返回一个Database.QueryLocator对象或一个包含传递给作业的记录或对象的Iterable。大多数时候,QueryLocator使用简单的SOQL查询来生成批处理作业中对象的范围。但是如果你需要做一些疯狂的事情,在传递给execute方法之前循环遍历API调用或预处理记录的结果,你可能想要查看参考资料部分中的Custom Iterators链接。使用QueryLocator对象,绕过由SOQL查询检索的记录总数的控制器限制,您可以查询多达5000万条记录。但是,对于Iterable,仍会强制执行由SOQL查询检索的记录总数的控制器限制。

execute():用于操作数据,形参中List为start()方法中返回的数据,可以直接对此List进行修改以达到批处理行为
对传递给方法的每个数据块或“批次”数据执行实际处理。默认批处理大小为200条记录。不能保证记录的批次按照从start方法接收的顺序执行。

此方法采用以下方法:
对Database.BatchableContext对象的引用。
sObject的列表,例如List <sObject>,或参数化类型的列表。如果使用Database.QueryLocator,请使用返回的列表。


finish():后期处理
用于执行后处理操作(例如,发送电子邮件),并在处理所有批次后调用一次。 这三步 称为一个周期。

模板:

global class MyBatchClass implements Database.Batchable<sObject> {

    global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {
        // collect the batches of records or objects to be passed to execute
    }

    global void execute(Database.BatchableContext bc, List<P> records){
        // process each batch of records
    }    

    global void finish(Database.BatchableContext bc){
        // execute any post-processing operations
    }    

}

  案例:

global class UpdateContactAddresses implements 
    Database.Batchable<sObject>, Database.Stateful {
    
    // instance member to retain state across transactions
    global Integer recordsProcessed = 0;

    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(
            'SELECT ID, BillingStreet, BillingCity, BillingState, ' +
            'BillingPostalCode, (SELECT ID, MailingStreet, MailingCity, ' +
            'MailingState, MailingPostalCode FROM Contacts) FROM Account ' + 
            'Where BillingCountry = \'USA\''
        );
    }

    global void execute(Database.BatchableContext bc, List<Account> scope){
        // process each batch of records
        List<Contact> contacts = new List<Contact>();
        for (Account account : scope) {
            for (Contact contact : account.contacts) {
                contact.MailingStreet = account.BillingStreet;
                contact.MailingCity = account.BillingCity;
                contact.MailingState = account.BillingState;
                contact.MailingPostalCode = account.BillingPostalCode;
                // add contact to list to be updated
                contacts.add(contact);
                // increment the instance member counter
                recordsProcessed = recordsProcessed + 1;
            }
        }
        update contacts;
    }    

    global void finish(Database.BatchableContext bc){
        System.debug(recordsProcessed + ' records processed. Shazam!');
        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, 
            JobItemsProcessed,
            TotalJobItems, CreatedBy.Email
            FROM AsyncApexJob
            WHERE Id = :bc.getJobId()];
        // call some utility to send email
        EmailUtils.sendMessage(a, recordsProcessed);
    }    

}

  

Testing Batch Apex:

@isTest
private class UpdateContactAddressesTest {

    @testSetup 
    static void setup() {
        List<Account> accounts = new List<Account>();
        List<Contact> contacts = new List<Contact>();
        // insert 10 accounts
        for (Integer i=0;i<10;i++) {
            accounts.add(new Account(name='Account '+i, 
                billingcity='New York', billingcountry='USA'));
        }
        insert accounts;
        // find the account just inserted. add contact for each
        for (Account account : [select id from account]) {
            contacts.add(new Contact(firstname='first', 
                lastname='last', accountId=account.id));
        }
        insert contacts;
    }

    static testmethod void test() {        
        Test.startTest();
        UpdateContactAddresses uca = new UpdateContactAddresses();
        Id batchId = Database.executeBatch(uca);
        Test.stopTest();

        // after the testing stops, assert records were updated properly
        System.assertEquals(10, [select count() from contact where MailingCity = 'New York']);
    }
    
}

  

 

转载于:https://www.cnblogs.com/bandariFang/p/6422522.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值