Desencadenadores de Apex masivos
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Escribir desencadenadores que funcionen en colecciones de sObjects.
- Escribir desencadenadores que realicen operaciones SOQL y DML eficientes.
Patrones de diseño de desencadenadores masivos
Los desencadenadores de Apex se han optimizado para funcionar de forma masiva. Se recomienda el uso de patrones de diseño masivos para procesar registros en desencadenadores. Mediante el uso de patrones de diseño masivos, se mejora el rendimiento de los desencadenadores, se consumen menos recursos de servidor y es menos probable que se superen los lÃmites de la plataforma.
La ventaja de procesar el código de forma masiva es que este puede procesar un elevado número de registros de forma eficaz y ejecutarse dentro de los lÃmites regulados en la plataforma Lightning. Estos lÃmites regulados se incluyen para garantizar que el código no controlado no monopolice los recursos de la plataforma de múltiples inquilinos.
En las siguientes secciones se describen los métodos principales para procesar de forma masiva el código Apex en desencadenadores (realización de operaciones en todos los registros del desencadenador y aplicación simultánea de SOQL y DML a colecciones de sObjects en lugar de a sObjects individuales). Las mejores prácticas de procesamiento masivo de SOQL y DML se aplican a todo el código Apex, lo que incluye SOQL y DML en clases. Los ejemplos incluidos se basan en desencadenadores y se usa la variable de contexto Trigger.new
.
Realización de operaciones en conjuntos de registros
En primer lugar, vamos a examinar el concepto de diseño masivo más básico de los desencadenadores. Los desencadenadores procesados de forma masiva realizan operaciones en todos los sObjects en el contexto de los desencadenadores. Normalmente, los desencadenadores realizan operaciones en un registro si la acción que ha activado el desencadenador se origina en la interfaz de usuario. Sin embargo, si el origen de la acción ha sido DML masivo o la API, el desencadenador realiza operaciones en un conjunto de registros en lugar de en un solo registro. Por ejemplo, si importa muchos registros con la API, los desencadenadores realizan operaciones en todo el conjunto de registros. Por consiguiente, una práctica de programación adecuada es dar por supuesto siempre que el desencadenador realiza operaciones en una colección de registros de modo que funcione en todos los casos.
En el caso del siguiente desencadenador (MyTriggerNotBulk
), se da por supuesto que tan solo un registro ha activado el desencadenador. Este desencadenador no funciona en un conjunto de registros completo si se insertan varios registros en la misma transacción. En el siguiente ejemplo se muestra una versión procesada de forma masiva.
Este ejemplo (MyTriggerBulk
) es una versión modificada de MyTriggerNotBulk
. Se usa un bucle for
para iterar en todos los sObjects disponibles. Este bucle funciona si Trigger.new
contiene un solo sObject o muchos sObjects.
Aplicación de SOQL masivo
Las consultas SOQL pueden ser muy útiles. Puede recuperar registros relacionados y comprobar una combinación de múltiples condiciones en una sola consulta. Las funciones de SOQL permiten escribir menos código y realizar menos consultas a la base de datos. La reducción del número de consultas a la base de datos contribuye a evitar alcanzar los lÃmites de consultas, los cuales se corresponden con 100 consultas SOQL para Apex sincrónico o 200 para Apex asÃncrono.
En el siguiente desencadenador (SoqlTriggerNotBulk
) se muestra un patrón de consulta SOQL que se debe evitar. En el ejemplo se realiza una consulta SOQL en un bucle for
para obtener las oportunidades relacionadas de cada cuenta, lo cual se ejecuta una vez para cada sObject de cuenta en Trigger.new
. Si tiene una larga lista de cuentas, una consulta SOQL en un bucle for
puede generar demasiadas consultas SOQL. En el siguiente ejemplo se muestra el método recomendado.
El siguiente ejemplo (SoqlTriggerBulk
) es una versión modificada de otra anterior y en él se muestra una mejor práctica para ejecutar consultas SOQL. La consulta SOQL hace la mayor parte del trabajo y se llama a ella una vez fuera del bucle principal.
- La consulta SOQL utiliza una consulta interna (
SELECT Id FROM Opportunities
) para obtener las oportunidades relacionadas de las cuentas. - La consulta SOQL se conecta a los registros del contexto del desencadenador mediante el uso de la cláusula
IN
y el enlace de la variableTrigger.new
en la cláusulaWHERE
(WHERE Id IN :Trigger.new
). Esta condiciónWHERE
filtra las cuentas para obtener solo los registros que han activado este desencadenador.
La combinación de las dos partes de los resultados de la consulta genera los registros correspondientes en una sola llamada (las cuentas de este desencadenador con las oportunidades relacionadas de cada cuenta).
Una vez obtenidos los registros y sus registros relacionados, el bucle for
itera en los registros de interés mediante el uso de la variable de colección (en este caso, acctsWithOpps
). La variable de colección contiene los resultados de la consulta SOQL. De este modo, el bucle for
itera solo en los registros en los que se van a realizar operaciones. Dado que ya se han obtenido los registros relacionados, no se requieren consultas adicionales en el bucle para obtener dichos registros.
De forma alternativa, si no necesita los registros principales de cuenta, puede recuperar solo las oportunidades relacionadas con las cuentas en el contexto de este desencadenador. Esta lista se especifica en la cláusula WHERE
mediante la coincidencia entre el campo AccountId
de la oportunidad con el ID
(Id.) de las cuentas de Trigger.new
: WHERE AccountId IN :Trigger.new
. Las oportunidades devueltas son para todas las cuentas en el contexto de este desencadenador y no para una cuenta especÃfica. En el siguiente ejemplo se muestra la consulta usada para obtener todas las oportunidades relacionadas.
Puede reducir el tamaño del ejemplo anterior mediante la combinación de la consulta SOQL con el bucle for
en una sola declaración: bucle for
de SOQL. A continuación, se muestra otra versión de este desencadenador masivo mediante un bucle for
de SOQL.
Aplicación de DML masivo
Al hacer llamadas a DML en un desencadenador o una clase, realice estas llamadas a DML en una colección de sObjects siempre que sea posible. La aplicación de DML a cada sObject individualmente implica un uso ineficiente de los recursos. El tiempo de ejecución de Apex permite hasta 150 llamadas a DML en una sola transacción.
Este desencadenador (DmlTriggerNotBulk
) realiza una llamada de actualización en un bucle for
que itera en las oportunidades relacionadas. Si se cumplen determinadas condiciones, el desencadenador actualiza la descripción de las oportunidades. En este ejemplo, se llama una vez a la declaración update de forma ineficiente para cada oportunidad. Si una operación de actualización de cuentas masiva activa el desencadenador, puede haber muchas cuentas. Si cada cuenta tiene una o dos oportunidades, podemos terminar fácilmente con más de 150 oportunidades. El lÃmite de la declaración DML es de 150 llamadas.
Este siguiente ejemplo (DmlTriggerBulk
) muestra cómo realizar declaraciones DML de forma masiva con una sola llamada a DML en una lista de oportunidades. En el ejemplo se agrega el sObject de oportunidad a una lista de oportunidades (oppsToUpdate
) en el bucle. A continuación, el desencadenador realiza la llamada a DML fuera del bucle en la lista una vez que se han agregado todas las oportunidades a la lista. Este patrón usa solo una llamada a DML con independencia del número de sObjects que se vayan a actualizar.
Proceso de patrón de diseño masivo: Ejemplo de obtención de registros relacionados
Vamos a aplicar los patrones de diseño que ya conoce mediante la escritura de un desencadenador que acceda a las oportunidades relacionadas de las cuentas. Modifique el ejemplo de desencadenador de la unidad anterior para el desencadenador AddRelatedRecord
. El desencadenador AddRelatedRecord
realiza operaciones de forma masiva, pero el de la unidad anterior no es tan eficiente como deberÃa, ya que itera en todos los registros del sObject Trigger.New
. En el siguiente ejemplo se modifican tanto el código del desencadenador como la consulta SOQL para obtener solo los registros de interés y, a continuación, iterar en dichos registros. Si no ha creado este desencadenador, no se preocupe, ya que puede hacerlo en esta sección.
Vamos a empezar revisando los requisitos para el desencadenador AddRelatedRecord
. El desencadenador se activa una vez que se insertan o actualizan las cuentas. El desencadenador agrega una oportunidad predeterminada para cada cuenta que aún no tenga ninguna oportunidad.
Antes que nada, las cuentas que se acaban de insertar nunca tienen una oportunidad predeterminada, asà que tenemos que agregar una. En el caso de las cuentas actualizadas, debemos determinar si ya tienen una oportunidad relacionada. Vamos a diferenciar cómo se procesan las inserciones y las actualizaciones mediante una declaración switch
en la variable de contexto Trigger.operationType
. A continuación, rastrearemos las cuentas que tenemos que procesar con una variable toProcess
. Por ejemplo:
Para todo tipo de inserciones de cuentas, solo tenemos que asignar las cuentas nuevas a la lista toProcess
:
En el caso de las actualizaciones, debemos determinar cuáles son las cuentas existentes de este desencadenador que no tienen ninguna oportunidad relacionada. Dado que este es un desencadenador posterior, podemos consultar los registros afectados en la base de datos. Esta es la declaración SOQL, el resultado de la asignación a la lista toProcess
.
Ahora usamos un bucle for
para iterar en la lista de cuentas de toProcess
y agregar una oportunidad relacionada predeterminada a oppList
. Una vez finalizado el proceso, agregamos de forma masiva la lista de oportunidades mediante la declaración DML insert
. Asà es como se crea o actualiza todo el desencadenador.
- Si ya ha creado el desencadenador
AddRelatedRecord
en la unidad anterior, modifÃquelo mediante la sustitución de su contenido por el siguiente desencadenador. En caso contrario, agregue el siguiente desencadenador mediante Developer Console y escribaAddRelatedRecord
como nombre del desencadenador. - Para probar el desencadenador, cree una cuenta en la interfaz de usuario de Salesforce y asÃgnele el nombre
Lions & Cats
. - En la lista relacionada Opportunities (Oportunidades) de la página de la cuenta, busque la oportunidad nueva
Lions & Cats
. El desencadenador ha agregado la oportunidad automáticamente.
Recursos