Apex - Processamento em lote
Neste capítulo, entenderemos o processamento em lote no Apex. Considere um cenário em que processaremos um grande número de registros diariamente, provavelmente a limpeza de dados ou talvez a exclusão de alguns dados não utilizados.
O que é o Batch Apex?
O Apex em lote é a execução assíncrona do código Apex, especialmente projetado para processar o grande número de registros e tem maior flexibilidade nos limites do governador do que o código síncrono.
Quando usar o Batch Apex?
Quando você deseja processar um grande número de registros diariamente ou mesmo em um intervalo de tempo específico, você pode ir para o Batch Apex.
Além disso, quando você deseja que uma operação seja assíncrona, você pode implementar o Apex em lote. O Batch Apex é exposto como uma interface que deve ser implementada pelo desenvolvedor. Os trabalhos em lote podem ser chamados programaticamente no tempo de execução usando o Apex. O Batch Apex opera em pequenos lotes de registros, cobrindo todo o seu conjunto de registros e dividindo o processamento em blocos de dados gerenciáveis.
Usando Batch Apex
Quando estamos usando o Batch Apex, devemos implementar a interface Database.Batchable fornecida pelo Salesforce e, em seguida, invocar a classe programaticamente.
Você pode monitorar a aula seguindo estas etapas -
Para monitorar ou interromper a execução do trabalho em lote do Apex Batch, vá para Configuração → Monitoramento → Trabalhos do Apex ou Trabalhos → Trabalhos do Apex.
A interface Database.Batchable possui os três métodos a seguir que precisam ser implementados -
- Start
- Execute
- Finish
Vamos agora entender cada método em detalhes.
Começar
O método Start é um dos três métodos da interface Database.Batchable.
Syntax
global void execute(Database.BatchableContext BC, list<sobject<) {}
Este método será chamado no início do Batch Job e coleta os dados nos quais o Batch Job estará operando.
Considere os seguintes pontos para entender o método -
Use o Database.QueryLocatorobjeto quando você está usando uma consulta simples para gerar o escopo dos objetos usados no trabalho em lote. Nesse caso, o limite de linha de dados SOQL será ignorado.
Use o objeto iterável quando tiver critérios complexos para processar os registros. Database.QueryLocator determina o escopo dos registros que devem ser processados.
Executar
Vamos agora entender o método Execute da interface Database.Batchable.
Syntax
global void execute(Database.BatchableContext BC, list<sobject<) {}
onde, list <sObject <é retornado pelo método Database.QueryLocator.
Este método é chamado após o método Start e faz todo o processamento necessário para o Batch Job.
Terminar
Vamos agora discutir o método Finish da interface Database.Batchable.
Syntax
global void finish(Database.BatchableContext BC) {}
Este método é chamado no final e você pode fazer algumas atividades de finalização, como enviar um e-mail com informações sobre os registros e status do trabalho em lote processado.
Exemplo de Apex em lote
Vamos considerar um exemplo de nossa empresa química existente e assumir que temos a necessidade de atualizar o campo Status do cliente e Descrição do cliente dos registros do cliente que foram marcados como ativos e que criaram a data como hoje. Isso deve ser feito diariamente e um e-mail deve ser enviado a um usuário sobre o status do processamento em lote. Atualize o status do cliente como 'Processado' e a descrição do cliente como 'Atualizado por meio de trabalho em lote'.
// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
global String [] email = new String[] {'[email protected]'};
// Add here your email address here
// Start Method
global Database.Querylocator start (Database.BatchableContext BC) {
return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
AND APEX_Active__c = true');
// Query which will be determine the scope of Records fetching the same
}
// Execute method
global void execute (Database.BatchableContext BC, List<sobject> scope) {
List<apex_customer__c> customerList = new List<apex_customer__c>();
List<apex_customer__c> updtaedCustomerList = new List<apex_customer__c>();
// List to hold updated customer
for (sObject objScope: scope) {
APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;
// type casting from generic sOject to APEX_Customer__c
newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
newObjScope.APEX_Customer_Status__c = 'Processed';
updtaedCustomerList.add(newObjScope); // Add records to the List
System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
}
if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
// Check if List is empty or not
Database.update(updtaedCustomerList); System.debug('List Size '
+ updtaedCustomerList.size());
// Update the Records
}
}
// Finish Method
global void finish(Database.BatchableContext BC) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
// Below code will fetch the job Id
AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
// get the job Id
System.debug('$$$ Jobid is'+BC.getJobId());
// below code will send an email to User about the status
mail.setToAddresses(email);
mail.setReplyTo('[email protected]'); // Add here your email address
mail.setSenderDisplayName('Apex Batch Processing Module');
mail.setSubject('Batch Processing '+a.Status);
mail.setPlainTextBody('The Batch Apex job processed'
+ a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
processed are'+a.JobItemsProcessed);
Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
}
}
Para executar este código, primeiro salve-o e cole o código a seguir em Executar anônimo. Isso criará o objeto da classe e o método Database.execute executará o trabalho Batch. Assim que o trabalho for concluído, um e-mail será enviado para o endereço de e-mail especificado. Certifique-se de ter um registro de cliente que tenhaActive conforme verificado.
// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProessingBatch();
Database.executeBatch (objClass);
Assim que esta aula for executada, verifique o endereço de e-mail que você forneceu, onde receberá o e-mail com as informações. Além disso, você pode verificar o status da tarefa em lote por meio da página Monitoramento e das etapas fornecidas acima.
Se você verificar os logs de depuração, poderá encontrar o tamanho da lista, que indica quantos registros foram processados.
Limitations
Podemos ter apenas 5 processamento de trabalhos em lote de cada vez. Esta é uma das limitações do Batch Apex.
Programando o Apex Batch Job usando a página de detalhes do Apex
Você pode agendar a classe Apex por meio da página de detalhes do Apex conforme fornecido abaixo -
Step 1 - Vá para Configuração ⇒ Classes Apex, clique em Classes Apex.
Step 2 - Clique no botão Agendar Apex.
Step 3 - Forneça detalhes.
Agendando o Apex Batch Job usando a Interface Agendável
Você pode agendar o Apex Batch Job usando a Interface Agendável conforme fornecido abaixo -
// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
global String [] email = new String[] {'[email protected]'};
// Add here your email address here
// Start Method
global Database.Querylocator start (Database.BatchableContext BC) {
return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
AND APEX_Active__c = true');
// Query which will be determine the scope of Records fetching the same
}
// Execute method
global void execute (Database.BatchableContext BC, List<sobject> scope) {
List<apex_customer__c> customerList = new List<apex_customer__c>();
List<apex_customer__c> updtaedCustomerList = new
List<apex_customer__c>();//List to hold updated customer
for (sObject objScope: scope) {
APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;//type
casting from generic sOject to APEX_Customer__c
newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
newObjScope.APEX_Customer_Status__c = 'Processed';
updtaedCustomerList.add(newObjScope);//Add records to the List
System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
}
if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
// Check if List is empty or not
Database.update(updtaedCustomerList); System.debug('List Size'
+ updtaedCustomerList.size());
// Update the Records
}
}
// Finish Method
global void finish(Database.BatchableContext BC) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
// Below code will fetch the job Id
AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];//get the job Id
System.debug('$$$ Jobid is'+BC.getJobId());
// below code will send an email to User about the status
mail.setToAddresses(email);
mail.setReplyTo('[email protected]');//Add here your email address
mail.setSenderDisplayName('Apex Batch Processing Module');
mail.setSubject('Batch Processing '+a.Status);
mail.setPlainTextBody('The Batch Apex job processed'
+ a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
processed are'+a.JobItemsProcessed);
Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
}
// Scheduler Method to scedule the class
global void execute(SchedulableContext sc) {
CustomerProessingBatch conInstance = new CustomerProessingBatch();
database.executebatch(conInstance,100);
}
}
// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProcessingBatch();
Database.executeBatch (objClass);