Apex - Traitement par lots

Dans ce chapitre, nous allons comprendre le traitement par lots dans Apex. Prenons un scénario dans lequel nous traiterons quotidiennement un grand nombre d'enregistrements, probablement le nettoyage des données ou peut-être la suppression de certaines données inutilisées.

Qu'est-ce que Batch Apex?

Batch Apex est une exécution asynchrone de code Apex, spécialement conçue pour traiter le grand nombre d'enregistrements et offre une plus grande flexibilité dans les limites du gouverneur que le code synchrone.

Quand utiliser Batch Apex?

  • Lorsque vous souhaitez traiter un grand nombre d'enregistrements quotidiennement ou même à une heure précise, vous pouvez opter pour Batch Apex.

  • De plus, lorsque vous souhaitez qu'une opération soit asynchrone, vous pouvez implémenter l'Apex par lots. Batch Apex est présenté comme une interface qui doit être implémentée par le développeur. Les travaux par lots peuvent être appelés par programme au moment de l'exécution à l'aide d'Apex. Batch Apex fonctionne sur de petits lots d'enregistrements, couvrant l'intégralité de votre jeu d'enregistrements et décomposant le traitement en blocs de données gérables.

Utilisation de Batch Apex

Lorsque nous utilisons Batch Apex, nous devons implémenter l'interface fournie par Salesforce Database.Batchable, puis appeler la classe par programme.

Vous pouvez surveiller la classe en suivant ces étapes -

Pour surveiller ou arrêter l'exécution du travail par lots Apex Batch, accédez à Configuration → Surveillance → Travaux ou travaux Apex → Travaux Apex.

L'interface Database.Batchable a les trois méthodes suivantes qui doivent être implémentées -

  • Start
  • Execute
  • Finish

Comprenons maintenant chaque méthode en détail.

Début

La méthode Start est l'une des trois méthodes de l'interface Database.Batchable.

Syntax

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

Cette méthode sera appelée au démarrage de la tâche Batch et collecte les données sur lesquelles la tâche Batch sera exécutée.

Tenez compte des points suivants pour comprendre la méthode -

  • Utilisez le Database.QueryLocatorobjet lorsque vous utilisez une requête simple pour générer la portée des objets utilisés dans le travail par lots. Dans ce cas, la limite de ligne de données SOQL sera contournée.

  • Utilisez l'objet itérable lorsque vous avez des critères complexes pour traiter les enregistrements. Database.QueryLocator détermine la portée des enregistrements qui doivent être traités.

Exécuter

Voyons maintenant la méthode Execute de l'interface Database.Batchable.

Syntax

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

où, list <sObject <est retourné par la méthode Database.QueryLocator.

Cette méthode est appelée après la méthode Start et effectue tout le traitement requis pour le traitement par lots.

terminer

Nous allons maintenant discuter de la méthode Finish de l'interface Database.Batchable.

Syntax

global void finish(Database.BatchableContext BC) {}

Cette méthode est appelée à la fin et vous pouvez effectuer certaines activités de finition telles que l'envoi d'un e-mail contenant des informations sur les enregistrements de travaux par lots traités et leur statut.

Exemple Apex par lots

Prenons un exemple de notre entreprise chimique existante et supposons que nous ayons l'obligation de mettre à jour le champ Statut du client et Description du client des enregistrements client qui ont été marqués comme actifs et qui ont créé la date comme aujourd'hui. Cela doit être fait quotidiennement et un e-mail doit être envoyé à un utilisateur sur l'état du traitement par lots. Mettez à jour le statut du client en tant que «traité» et la description du client en tant que «mise à jour via un traitement par lots».

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

Pour exécuter ce code, enregistrez-le d'abord, puis collez le code suivant dans Execute anonymous. Cela créera l'objet de la classe et la méthode Database.execute exécutera le travail par lots. Une fois le travail terminé, un e-mail sera envoyé à l'adresse e-mail spécifiée. Assurez-vous que vous disposez d'un dossier clientActive comme vérifié.

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

Une fois ce cours exécuté, vérifiez l'adresse e-mail que vous avez fournie à laquelle vous recevrez l'e-mail avec les informations. En outre, vous pouvez vérifier l'état du travail par lots via la page Surveillance et les étapes décrites ci-dessus.

Si vous vérifiez les journaux de débogage, vous pouvez trouver la taille de la liste qui indique le nombre d'enregistrements traités.

Limitations

Nous ne pouvons avoir que 5 traitements par lots à la fois. C'est l'une des limitations de Batch Apex.

Planification de la tâche Apex Batch à l'aide de la page de détails Apex

Vous pouvez planifier la classe Apex via la page de détails Apex comme indiqué ci-dessous -

Step 1 - Allez dans Setup ⇒ Apex Classes, cliquez sur Apex Classes.

Step 2 - Cliquez sur le bouton Planifier Apex.

Step 3 - Fournissez des détails.

Planification de la tâche Apex Batch à l'aide de l'interface de planification

Vous pouvez planifier le travail par lots Apex à l'aide de l'interface planifiable comme indiqué ci-dessous -

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