Apex: procesamiento por lotes

En este capítulo, comprenderemos el procesamiento por lotes en Apex. Considere un escenario en el que procesaremos una gran cantidad de registros a diario, probablemente la limpieza de datos o tal vez eliminando algunos datos no utilizados.

¿Qué es Batch Apex?

Batch Apex es una ejecución asincrónica de código Apex, especialmente diseñado para procesar una gran cantidad de registros y tiene mayor flexibilidad en los límites del regulador que el código síncrono.

¿Cuándo usar Batch Apex?

  • Cuando desee procesar una gran cantidad de registros a diario o incluso en un intervalo de tiempo específico, puede optar por Batch Apex.

  • Además, cuando desee que una operación sea asincrónica, puede implementar Batch Apex. Batch Apex se expone como una interfaz que debe implementar el desarrollador. Los trabajos por lotes se pueden invocar mediante programación en tiempo de ejecución mediante Apex. Batch Apex opera sobre pequeños lotes de registros, cubriendo todo su conjunto de registros y dividiendo el procesamiento en fragmentos de datos manejables.

Uso de Batch Apex

Cuando usamos Batch Apex, debemos implementar la interfaz Database.Batchable proporcionada por Salesforce y luego invocar la clase mediante programación.

Puede monitorear la clase siguiendo estos pasos:

Para monitorear o detener la ejecución del trabajo por lotes Apex Batch, vaya a Configuración → Monitoreo → Trabajos Apex o Trabajos → Trabajos Apex.

Database.Batchable interfaz tiene los siguientes tres métodos que deben implementarse:

  • Start
  • Execute
  • Finish

Entendamos ahora cada método en detalle.

comienzo

El método Start es uno de los tres métodos de la interfaz Database.Batchable.

Syntax

global void execute(Database.BatchableContext BC, list<sobject<) {}

Este método se llamará al inicio del trabajo por lotes y recopila los datos en los que funcionará el trabajo por lotes.

Considere los siguientes puntos para comprender el método:

  • Utilizar el Database.QueryLocatorobjeto cuando está utilizando una consulta simple para generar el alcance de los objetos utilizados en el trabajo por lotes. En este caso, se omitirá el límite de filas de datos SOQL.

  • Utilice el objeto iterable cuando tenga criterios complejos para procesar los registros. Database.QueryLocator determina el alcance de los registros que deben procesarse.

Ejecutar

Entendamos ahora el método Execute de la interfaz Database.Batchable.

Syntax

global void execute(Database.BatchableContext BC, list<sobject<) {}

donde, list <sObject <es devuelto por el método Database.QueryLocator.

Este método se llama después del método Start y realiza todo el procesamiento necesario para el trabajo por lotes.

Terminar

Ahora discutiremos el método Finish de la interfaz Database.Batchable.

Syntax

global void finish(Database.BatchableContext BC) {}

Este método se llama al final y puede realizar algunas actividades de acabado, como enviar un correo electrónico con información sobre los registros de trabajo por lotes procesados ​​y el estado.

Ejemplo de lote de Apex

Consideremos un ejemplo de nuestra Compañía Química existente y supongamos que tenemos el requisito de actualizar el campo Estado del cliente y Descripción del cliente de los Registros del cliente que se han marcado como Activos y que se han creado como Fecha como hoy. Esto debe hacerse a diario y se debe enviar un correo electrónico a un usuario sobre el estado del procesamiento por lotes. Actualice el estado del cliente como 'Procesado' y la descripción del cliente como 'Actualizado mediante trabajo por lotes'.

// 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 ejecutar este código, primero guárdelo y luego pegue el siguiente código en Ejecutar anónimo. Esto creará el objeto de la clase y el método Database.execute ejecutará el trabajo por lotes. Una vez que se complete el trabajo, se enviará un correo electrónico a la dirección de correo electrónico especificada. Asegúrese de tener un registro de cliente que tengaActive como se marcó.

// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProessingBatch();
Database.executeBatch (objClass);

Una vez que se ejecute esta clase, verifique la dirección de correo electrónico que proporcionó donde recibirá el correo electrónico con la información. Además, puede verificar el estado del trabajo por lotes a través de la página de Monitoreo y los pasos indicados anteriormente.

Si comprueba los registros de depuración, puede encontrar el tamaño de la lista que indica cuántos registros se han procesado.

Limitations

Solo podemos procesar 5 trabajos por lotes a la vez. Esta es una de las limitaciones de Batch Apex.

Programación del trabajo por lotes de Apex mediante la página de detalles de Apex

Puede programar la clase de Apex a través de la página de detalles de Apex como se indica a continuación:

Step 1 - Vaya a Configuración ⇒ Clases Apex, haga clic en Clases Apex.

Step 2 - Haga clic en el botón Schedule Apex.

Step 3 - Proporcione detalles.

Programación del trabajo por lotes de Apex mediante la interfaz programable

Puede programar el trabajo por lotes de Apex utilizando la interfaz programable como se indica a continuación:

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