Apex - Пакетная обработка

В этой главе мы разберемся с пакетной обработкой в ​​Apex. Рассмотрим сценарий, при котором мы будем обрабатывать большое количество записей ежедневно, возможно, очищая данные или, возможно, удаляя некоторые неиспользуемые данные.

Что такое Batch Apex?

Пакетная обработка Apex - это асинхронное выполнение кода Apex, специально разработанное для обработки большого количества записей и обладающее большей гибкостью в ограничениях регулятора, чем синхронный код.

Когда использовать Batch Apex?

  • Если вы хотите обрабатывать большое количество записей ежедневно или даже в определенный промежуток времени, вы можете выбрать Batch Apex.

  • Кроме того, если вы хотите, чтобы операция была асинхронной, вы можете реализовать Batch Apex. Пакетная Apex представлена ​​как интерфейс, который должен быть реализован разработчиком. Пакетные задания можно запускать программно во время выполнения с помощью Apex. Пакетная обработка Apex работает с небольшими пакетами записей, охватывая весь ваш набор записей и разбивая обработку на управляемые фрагменты данных.

Использование Batch Apex

Когда мы используем Batch Apex, мы должны реализовать предоставленный Salesforce интерфейс Database.Batchable, а затем программно вызвать класс.

Вы можете отслеживать класс, выполнив следующие действия:

Чтобы отслеживать или останавливать выполнение пакетного задания Apex Batch, выберите «Настройка» → «Мониторинг» → «Задания Apex» или «Задания» → «Задания Apex».

Интерфейс Database.Batchable имеет следующие три метода, которые необходимо реализовать:

  • Start
  • Execute
  • Finish

Давайте теперь разберемся с каждым методом подробно.

Начало

Метод Start - один из трех методов интерфейса Database.Batchable.

Syntax

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

Этот метод вызывается при запуске пакетного задания и собирает данные, с которыми будет работать пакетное задание.

Рассмотрим следующие моменты, чтобы понять метод -

  • Использовать Database.QueryLocatorobject, когда вы используете простой запрос для создания области объектов, используемых в пакетном задании. В этом случае ограничение на количество строк данных SOQL будет обойдено.

  • Используйте итеративный объект, когда у вас есть сложные критерии для обработки записей. Database.QueryLocator определяет объем записей, которые должны быть обработаны.

Выполнить

Давайте теперь разберемся с методом Execute интерфейса Database.Batchable.

Syntax

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

где list <sObject <возвращается методом Database.QueryLocator.

Этот метод вызывается после метода Start и выполняет всю обработку, необходимую для пакетного задания.

Конец

Теперь мы обсудим метод Finish интерфейса Database.Batchable.

Syntax

global void finish(Database.BatchableContext BC) {}

Этот метод вызывается в конце, и вы можете выполнить некоторые завершающие действия, например отправить электронное письмо с информацией об обработанных записях пакетного задания и статусе.

Пакетный пример Apex

Давайте рассмотрим пример нашей существующей химической компании и предположим, что у нас есть требование обновить поля «Статус клиента» и «Описание клиента» в записях клиентов, которые были помечены как «Активные» и для которых создана Дата как сегодня. Это следует делать ежедневно, и пользователю следует отправлять электронное письмо о статусе пакетной обработки. Обновите статус клиента как «Обработано», а описание клиента - как «Обновлено с помощью пакетного задания».

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

Чтобы выполнить этот код, сначала сохраните его, а затем вставьте следующий код в Execute anonymous. Это создаст объект класса, а метод Database.execute выполнит пакетное задание. После завершения работы на указанный адрес электронной почты будет отправлено электронное письмо. Убедитесь, что у вас есть запись о клиенте,Active как проверено.

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

Как только этот класс будет выполнен, проверьте указанный вами адрес электронной почты, на который вы получите электронное письмо с информацией. Кроме того, вы можете проверить статус пакетного задания на странице «Мониторинг» и выполнить указанные выше действия.

Если вы проверите журналы отладки, вы можете найти размер списка, который указывает, сколько записей было обработано.

Limitations

Мы можем обрабатывать только 5 пакетных заданий одновременно. Это одно из ограничений Batch Apex.

Планирование пакетного задания Apex с помощью страницы сведений о Apex

Вы можете запланировать класс Apex на странице сведений о Apex, как показано ниже -

Step 1 - Перейдите в «Настройка» ⇒ «Классы Apex», нажмите «Классы Apex».

Step 2 - Щелкните кнопку Schedule Apex.

Step 3 - Сообщите подробности.

Планирование пакетного задания Apex с помощью настраиваемого интерфейса

Вы можете запланировать пакетное задание Apex с помощью настраиваемого интерфейса, как показано ниже -

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