💻 DESENVOLVIMENTO · APEX
Apex Triggers: Guia Completo
⏱️ 12 min de leitura
✍️ Equipe Haza Solutions
📅 Junho de 2026
O que é um Apex Trigger?
Um Apex Trigger é um bloco de código que é executado automaticamente em resposta a eventos específicos no Salesforce, como inserção, atualização, exclusão ou restauração de registros. Triggers são a base da automação avançada no Salesforce.
Diferente de Flows (que são visuais e mais simples), Triggers são escritos em código Apex e oferecem controle total sobre a lógica de negócio, permitindo validações complexas, cálculos, integrações e automações que não são possíveis com ferramentas de baixo código.
"Triggers mal implementados são a causa número 1 de problemas de performance no Salesforce. Entender ordem de execução e evitar loops infinitos é essencial para qualquer desenvolvedor."
Anatomia de um Apex Trigger
Veja a estrutura básica de um trigger:
Estrutura Básica de um Trigger
trigger AccountTrigger on Account (before insert, after insert, before update, after update) {
if (Trigger.isBefore) {
if (Trigger.isInsert) {
AccountTriggerHandler.beforeInsert(Trigger.new);
}
if (Trigger.isUpdate) {
AccountTriggerHandler.beforeUpdate(Trigger.new, Trigger.oldMap);
}
}
if (Trigger.isAfter) {
if (Trigger.isInsert) {
AccountTriggerHandler.afterInsert(Trigger.new);
}
if (Trigger.isUpdate) {
AccountTriggerHandler.afterUpdate(Trigger.new, Trigger.oldMap);
}
}
}
Componentes principais:
- trigger — Palavra-chave que define um trigger
- AccountTrigger — Nome do trigger (deve ser único e descritivo)
- on Account — Objeto sobre o qual o trigger atua
- (before insert, after insert, ...) — Eventos que disparam o trigger
- Trigger.new — Lista de novos registros sendo inseridos/atualizados
- Trigger.oldMap — Mapa dos valores antigos (apenas em updates)
- Trigger.isBefore / Trigger.isAfter — Variáveis de contexto para identificar quando o trigger executa
Eventos de Trigger (Trigger Events)
Existem 8 eventos principais que disparam triggers:
Before Insert
Timing: Antes de inserir
Executado antes do registro ser inserido no banco de dados. Ideal para validações e modificações de dados antes da inserção.
Caso de uso: Validar dados, preencher campos padrão, verificar duplicatas
After Insert
Timing: Depois de inserir
Executado após o registro ser inserido. Neste ponto, o registro já tem um ID. Use para criar registros relacionados.
Caso de uso: Criar registros filhos, atualizar contadores, enviar notificações
Before Update
Timing: Antes de atualizar
Executado antes de atualizar um registro. Você tem acesso aos valores antigos e novos para comparação.
Caso de uso: Validar mudanças, impedir alterações de campos críticos, auditar
After Update
Timing: Depois de atualizar
Executado após a atualização. Ideal para lógicas que dependem do novo estado do registro.
Caso de uso: Atualizar registros relacionados, enviar alertas, sincronizar dados
Ordem de Execução (Execution Order)
Quando você salva um registro no Salesforce, uma sequência complexa de eventos ocorre:
- Sistema executa validações de campo (required, type, etc.)
- Triggers BEFORE são executados
- Sistema executa validações de regra (validation rules)
- Registro é inserido/atualizado no banco de dados
- Triggers AFTER são executados
- Workflows e Process Builder são executados
- Flows são executados
- Escalações são processadas
- Ações de email são enviadas
- Transação é concluída
Importante: Se um trigger BEFORE falhar, o registro não é inserido e os triggers AFTER não são executados. Se um trigger AFTER falhar, o registro já foi salvo, mas a transação é revertida.
Como Evitar Loops Infinitos
Um dos maiores problemas em triggers é o loop infinito: um trigger atualiza um registro, o que dispara outro trigger, que atualiza o mesmo registro novamente, e assim por diante.
Padrão: Usar Flag Estático para Evitar Loop
public class AccountTriggerHandler {
private static Boolean isExecuting = false;
public static void beforeUpdate(List<Account> newAccounts, Map<Id, Account> oldMap) {
if (isExecuting) return; // Evita re-execução
isExecuting = true;
for (Account acc : newAccounts) {
Account oldAcc = oldMap.get(acc.Id);
if (acc.BillingCity != oldAcc.BillingCity) {
acc.ShippingCity = acc.BillingCity;
}
}
isExecuting = false;
}
}
Boas Práticas
1. Um Trigger por Objeto
Crie apenas UM trigger por objeto. Todos os eventos devem estar no mesmo trigger para evitar conflitos de ordem de execução.
2. Separar Lógica em Handler Classes
Coloque a lógica de negócio em classes separadas (handlers), não no trigger. Isso melhora testabilidade e manutenção.
3. Sempre Usar Bulk Processing
Triggers processam múltiplos registros por vez. Use loops para iterar sobre Trigger.new/Trigger.old, não operações individuais.
4. Evitar Queries em Loops
NUNCA faça queries dentro de um loop for. Você pode atingir o limite de 100 queries por transação. Use Maps e pre-queries em vez disso.
5. Sempre Adicionar Testes
Escreva testes unitários para seus triggers. Cobertura mínima é 75%, mas aim para 90%+.
Exemplo Prático Completo
Vamos criar um trigger que sincroniza o endereço de cobrança com o endereço de entrega:
Trigger: Sincronizar Endereços
trigger AccountAddressTrigger on Account (before insert, before update) {
AccountAddressHandler.syncAddresses(Trigger.new, Trigger.oldMap);
}
public class AccountAddressHandler {
private static Boolean isExecuting = false;
public static void syncAddresses(List<Account> newAccounts, Map<Id, Account> oldMap) {
if (isExecuting) return;
isExecuting = true;
for (Account acc : newAccounts) {
if (oldMap == null) {
acc.ShippingStreet = acc.BillingStreet;
acc.ShippingCity = acc.BillingCity;
acc.ShippingState = acc.BillingState;
acc.ShippingPostalCode = acc.BillingPostalCode;
acc.ShippingCountry = acc.BillingCountry;
} else {
Account oldAcc = oldMap.get(acc.Id);
if (acc.BillingStreet != oldAcc.BillingStreet ||
acc.BillingCity != oldAcc.BillingCity) {
acc.ShippingStreet = acc.BillingStreet;
acc.ShippingCity = acc.BillingCity;
acc.ShippingState = acc.BillingState;
acc.ShippingPostalCode = acc.BillingPostalCode;
acc.ShippingCountry = acc.BillingCountry;
}
}
}
isExecuting = false;
}
}
Precisa de Ajuda com Apex Triggers?
A Haza Solutions ajuda empresas a implementar soluções Apex robustas, escaláveis e bem testadas.
Falar com um Especialista →
Perguntas Frequentes
Qual é a diferença entre Trigger.new e Trigger.newMap?
Trigger.new é uma lista de registros. Trigger.newMap é um mapa com Id como chave e registro como valor. Use newMap quando precisar fazer lookup rápido por ID.
Posso atualizar um registro dentro de um trigger AFTER INSERT?
Sim, mas você deve usar Database.update() ou update statement. Evite atualizar o registro dentro do trigger AFTER do mesmo objeto (causa loop).
Quantos triggers posso ter por objeto?
Tecnicamente, você pode ter múltiplos, mas a best practice é ter apenas UM trigger por objeto. Se você tiver múltiplos triggers, a ordem de execução não é garantida.
Como debugar um trigger?
Use System.debug() para imprimir valores no log. Acesse Setup > Logs > Debug Logs. Você também pode usar o Apex Debugger em VS Code para debugging interativo.