What is a Salesforce Trigger?  A trigger is an action that can be fired on an object when a particular event (insert, update or delete) occurs.

For example when you create a lead (no matter how you get it) based on the Zip Code you may need to route the lead to the correct salesperson.  In this example I have a Zip Code Territories Object which groups the Zip Codes based on whatever collection criteria a company sees fit.  So when a Lead is inserted or updated then an action must occur which consists of a lookup into the Zip Code Territories Object to send the Territory name (custom field added to the Lead) which will fire a workflow that sends an email.

Typically a trigger should follow a design pattern. Each trigger has a limit of 250 SOQL calls you can make. So if you need to execute queries you must have a trigger loop to build a selection set for limiting the SOQL call to a single Selection of a set of values (SELECT .. WHERE .. IN <list>)

A good design pattern is to create the trigger stub on the Object (n this case the Lead) and create a class which handles the code for the trigger.  Why do this? Why not put the code directly into the trigger?  There are a number of valid reasons, but for me, it’s the fact that i can write and test the code in Execute Anonymous without having to add/update or delete a record.


Trigger stubTrigger on Lead(before insert, before update)
{
    LeadTriggerHandler handler = new LeadTriggerHandler();
    if(trigger.isInsert)
    {
        LeadTriggerHandler.handleInsert(trigger.new);
    }
    else
    {
        LeadTriggerHandler.handleUpdate(trigger.new);
    }
}

So as you can see the Trigger does nothing but pass the list of Objects to be inserted or updated to a Class written to handle the logic. In this case LeadTriggerHandler.


public class with sharing LeadTriggerHandler()
{
    public LeadTriggerHandler()
    {
        // code for initialization
    }

    public void handleInsert(List listOfLeads)
    {
        // code for Insert handler
    }

    public void handleUpdate(List listOfLeads)
    {
        // code for update handler
    }
}

So let’s build out the example and put all this into context. So you have a zip code territory Object (Zip_Territory) and a related field on the Lead called Territory__c. So In the add of a new Lead we want to find the Territory name and place it in the Lead.

So the first thing we need to do is create a Set of Zip Codes from the collection of inserted Leads. Because we later want to Query ONLY those zip codes we need from the Zip_Territory Object. Triggers have a governor limit of 250 SOQL queries. To prevent our trigger from calling to many queries and looping we need to use two special data types. A Set<> and a Map<>.

A Set<> object is a list of data such as [A, B, C]. So in this example the zip code(s) might be
[76227]
[75024]
[75034]

A Map is a keyed list, so it might be like this for our Example:
[76227 : “Aubrey”]
[75024 : “Frisco”]
[75034 : “Plano” ]

So when we make a look up call to the map object for 76227 it should return the string name “Aubrey”.

The design should be like so:

1. Trigger fires on Insert only
2. Create a Set of Look Up Values
3. Query the Look Up Object for ONLY the set values
4. Place the set values into a Map for use by the Primary Object
5. Set the value from the Map into the Primary Object

So we return to our original stub trigger that we wrote earlier and name it LeadUpdateTrigger.


Trigger LeadUpdateTrigger on Lead(before insert, before update)
{
    LeadTriggerHandler handler = new LeadTriggerHandler();
    if(trigger.isInsert)
    {
        LeadTriggerHandler.handleInsert(trigger.new);
    }
}

Now we must modify the LeadTriggerHandler to have our Set and Map objects and to do the actual look up.


public class with sharing LeadTriggerHandler()
{
    public Set<String> setOfZipCodes;
    public Map<String, String> mapOfTerritory;

    public LeadTriggerHandler()
    {
        // code for initialization
        setOfZipCodes = new Set();
        mapOfTerritory = new Map<String, String>();
    }

    public void handleInsert(List<Lead> listOfLeads)
    {
        // code for Insert handler
        buildSetAndMap(listOfLeads);

        // Because we built the map we know that
        // we can loop through the Leads and pull the 
        // Territory name back from the map
        for(Lead l : listOfLeads)
        {
            l.Territory__c = mapOfTerritory.get(l.PostalCode);
        }
    }

    // private function to build the Set and Map
    private void buildSetAndMap(List listOfLeads)
    {
        for(Lead l : listOfLeads)
        {
            setOfZipCodes.add(l.PostalCode);
        }
 
        // This is where we use the Set<> to query ONLY the 
        // Zip Code Territory Records we have in our list
        for(Zip_Territory__c z : [SELECT Zip__c, Territory__c 
                                  FROM Zip_Territory__c 
                                  WHERE Zip__c IN :setOfZipCodes])
        {
             mapOfTerritory.put(z.Zip__c, z.Territory__c);
        }
    }

}

There you have it. A simple trigger example with the building blocks you need to create your own bulk managed triggers.

[contact-form]