Tag Archives: Apex Trigger

Salesforce Apex Trigger Events

  • Before Insert: Trigger that executes due to an insert operation and before the record is saved to the database it is a before Insert trigger
  • Before Update: Trigger that executes due to an update operation and before the record is saved to the database it is a before update trigger
  • Before Delete: Trigger that executes due to a delete operation and before the record is saved to the database it is a before delete trigger
  • After Insert: Trigger that executes due to an insert operation but after the record is saved to the database it is an after Insert trigger
  • After Update: Trigger that executes due to an update operation and after the record is saved to the database it is an after update trigger
  • After Delete: Trigger that executes due to a delete operation and after the record is deleted from the database it is an after delete trigger
  • After Undelete: Trigger that executes due to a undelete operation and after the record is undeleted from the database it is an after undelete trigger

Compare Old And New Values In Salesforce Trigger

Salesforce provides trigger.oldmap where in all the old records are stored in map with keyset as their ids. We can compare old field value of records with the new values in trigger.

Here in the below example, the trigger compares the account number old value with the new value. If the account number is changed the trigger assigns the type field value “Customer – Direct” else it assigns it a value “Customer – Channel”.

trigger AccountTrigger on Account (before update) {
    
    for (Account acc: Trigger.new) {
        Account oldAccount = Trigger.oldMap.get(acc.Id);
        if(acc.AccountNumber != oldAccount.AccountNumber) {
            System.debug('--Account Number is changed--');
            System.debug('--Old Account Number -' + oldAccount.AccountNumber);
            System.debug('--New Account Number -' + acc.AccountNumber);
            acc.Type = 'Customer - Direct';
        }
        else{
            System.debug('--Account Number has not been updated--');
            acc.Type = 'Customer - Channel';  
        }
    }
}

Bulkify Apex Trigger in Salesforce

Bulkifying Apex Trigger refers to the concept of making sure the code properly handles more than one record at a time. When a batch of records initiates Apex, a single instance of that Apex code is executed, but it needs to handle all of the records in that given batch.

For example, a trigger could be invoked by an Force.com SOAP API call that inserted a batch of records. So if a batch of records invokes the same Apex trigger, all of those records need to be processed as a bulk, in order to write scalable code and avoid hitting governor limits.

Here is a simple example of some Apex code both bulkified, and not bulkified.

Not Bulkified:

trigger AccountTriggr on Account (before update) {
    
    //This only handles the first record in the Trigger.new collection
    //But if more than one Account initiated this trigger, those additional records
    //will not be processed
    Account acc = Trigger.new[0];
    List<Contact> conList = [SELECT Id, FirstName, LastName, Email, Phone FROM Contact WHERE AccountId = :acc.Id];
}

In above apex trigger the issue is that only one Account record is handled because the code explicitly accesses only the first record in the Trigger.new collection by using Trigger.new[0]. Instead, the trigger should properly handle the entire collection of Accounts in the Trigger.new collection.

Bulkified:

trigger AccountTriggr on Account (before update) {
    
    //Loop through all records in the Trigger.new collection
    for(Account a: Trigger.new){
        //Write your logic
    }
}

In above bulkified apex trigger the code iterates across the entire Trigger.new collection with a for loop. Now if this trigger is invoked with a single Account or up to 200 Accounts, all records are properly processed.

Call Batch Apex From Apex Trigger

Batch Apex Class:

global class AccountBatchApex implements Database.Batchable<sobject>{
    
    global Database.Querylocator start(Database.BatchableContext bc){
        String soqlQuery = 'SELECT Name, AccountNumber, Type From Account';
        return database.getquerylocator(soqlQuery);
    }
    
    global void execute(Database.BatchableContext bc, List<Account> scope){
        for(Account acc: scope){
            //Write your logic
        }  
    }
    
    Public void finish(Database.BatchableContext bc){ 
    }
}

Apex Trigger:

trigger AccountTrigger on Account (after insert) {
    List<Account> accList = new List<Account>();
    for(Account acc : trigger.new){
        if(acc.Type.equals('Customer - Direct')){
            accList.add(acc);
        }
    }
    
    if(accList.size() > 0){
        AccountBatchApex objBatch = new AccountBatchApex();
        Database.executebatch(objBatch,200);
    }
}