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);