Apex Triggers in Salesforce
• Apex Triggers are event handlers. Whenever a record is inserted, updated, deleted, or undeleted the Salesforce.com system will “fire” or execute the trigger event.
• Salesforce will actually execute a
trigger in two different contexts: before and after.
• Before-trigger events are executed
before a record has been committed to the database.
• While after-trigger events are
executed after a record is committed to the database.
When to use Before Trigger
•Before-trigger events occur before
a record’s changes are committed to the database.
• This particular event is ideal for
performing data validation, setting default values, or performing additional
logic and/or calculations.
• Please keep in mind that in the
case of before-insert events, because the event is executed before the record
is committed to the database it will not have a record id.
•Before-triggers in my opinion are
the most efficient and are going to be your goto method for most of the
triggers you will write for a couple of reasons.
• The first being that you can
perform data validation and reject a record before it is committed to the
database, meaning there is no cost to performance by the system having to roll
back an update.
• Second, you can update fields or
set default values for a record without having to initiate another DML command.
For example
the code below illustrates setting a default value on a record. No DML
required.
trigger setDefaultAccountValues on Account (before insert, before update) {
for (Account oAccount : trigger.new) {
oAccount.Industry =
‘Cloud Computing’;
}
}
…and
that is it. As you can see I simply just set the value of the field I want to
change or default. Salesforce will take care of the rest.
When to use After Trigger
•After-trigger events occur after a record has
been committed to the database, which means that records being inserted will
have a record id available.
• This particular event is ideal for
working with data that is external to the record itself such as referenced
objects or creating records based on information from the triggered object.
• Another key best practice for after-trigger
events is that while it is possible to perform a DML operation on the record
that initiated the trigger event, it should be avoided.
• If we think it through, when you perform a DML
operation on a record from a trigger event the system will need to execute all
triggers on that object again, not only does this impact performance but it
puts us at risk of creating an infinite loop
For example the code below illustrates creating an
Opportunity after an Account is created
trigger
createNewAccountOpportunity on
Account (after insert) {
List<Opportunity> listOpportunities = new List<Opportunity>();
for (Account oAccount : trigger.new) {
Opportunity oOpportunity = new Opportunity();
oOpportunity.Name = oAccount.Name;
oOpportunity.AccountId = oAccount.Id;
oOpportunity.Stage = ‘Proposal’;
oOpportunity.CloseDate = System.today() + 30; //Closes 30 days from today
listOpportunities.add(oOpportunity);
}
if (listOpportunities.isEmpty() == false) {
insert listOpportunities ;
}
}
Example 2 :
trigger exampleInvalidTrigger on
Opportunity (before
insert, before
update) {
for (Opportunity
oOpportunity : trigger.new) {
if (oOpportunity.Owner.Profile.Name ==
‘Executive’) {
oOpportunity.IsExecutiveOpportunity = true;
}
}
}
Example 3 :
trigger exampleValidTrigger on
Opportunity (before
insert, before
update) {
Map<Id, User>
mapUsers = new Map<Id, User>([SELECT
Id, Profile.Name FROM User]);
for (Opportunity
oOpportunity : trigger.new) {
User oOwner = mapUsers.get(oOpportunity.OwnerId);
if (oOwner.Profile.Name ==
‘Executive’) {
oOpportunity.IsExecutiveOpportunity = true;
}
}
}
Writing Bulk Trigger
•All triggers
execute in batch mode, meaning whether it is single record or a hundred you
will always need to use the trigger.new collection .
• We should prepare your trigger to be able to
handle a batch of records.
• We have
to take care on how we query additional information and also keep in mind how
many script statements we are executing per record.
"Bad Example"
trigger badExample on Opportunity (before
insert, before
update) {
for (Opportunity
oOpportunity : trigger.new) {
User oOwner = [SELECT
Id, Profile.Name FROM
User WHERE Id =
:oOpportunity.Id];
if (oOwner.Profile.Name ==
‘Executive’) {
oOpportunity.IsExecutiveOpportunity = true;
}
}
}
"Good Example but not worthy enough"
trigger exampleGoodButInefficientTrigger on
Opportunity (before
insert, after update) {
Map<Id, User>
mapUsers = new Map<Id, User>([SELECT
Id, Profile.Name FROM User]);
for (Opportunity
oOpportunity : trigger.new) {
User oOwner = mapUsers.get(oOpportunity.OwnerId);
if (oOwner.Profile.Name ==
‘Executive’) {
oOpportunity.IsExecutiveOpportunity = true;
}
}
}
"Better Example"
trigger exampleBetterTrigger on
Opportunity (before
insert, after update) {
Set<Id>
ownerIds = new Set<Id>();
for (Opportunity
oOpportunity : trigger.new) {
ownerIds.add(oOpportunity.OwnerId);
}
Map<Id, User>
mapUsers = new Map<Id, User>([SELECT
Id, Profile.Name FROM
User WHERE Id IN :ownerIds]);
for (Opportunity
oOpportunity : trigger.new) {
User oOwner = mapUsers.get(oOpportunity.OwnerId);
if (oOwner.Profile.Name ==
‘Executive’) {
oOpportunity.IsExecutiveOpportunity = true;
}
}
}
"Best Example"
trigger exampleBestTrigger on
Opportunity (before
insert, after update) {
Set<Id>
oppIds = trigger.newMap.keySet();
Map<Id, User>
mapUsers = new Map<Id, User>([SELECT
Id, Profile.Name
FROM
User WHERE Id IN (SELECT
OwnerId FROM
Opportunity
WHERE Id IN :oppIds)]);
for (Opportunity
oOpportunity : trigger.new) {
User oOwner = mapUsers.get(oOpportunity.OwnerId);
if (oOwner.Profile.Name ==
‘Executive’) {
oOpportunity.IsExecutiveOpportunity = true;
}
}
}
//Single Trigger for Before and
After Events
trigger AccountEventListener on
Account (before
insert, after insert, before
update, after update) {
if (trigger.isBefore) {
if (trigger.isInsert ||
trigger.isUpdate) {
//DO
SOMETHING
}
}
else if (trigger.isAfter) {
if (trigger.isInsert ||
trigger.isUpdate) {
//DO
SOMETHING
}
}
}
//Before Event Trigger
trigger AccountBeforeEventListener on
Account (before
insert, before
update) {
if (trigger.isInsert ||
trigger.isUpdate) {
//DO
SOMETHING
}
}
//After Event Trigger
trigger AccountAfterEventListener on
Account (after insert, after update) {
if (trigger.isInsert ||
trigger.isUpdate) {
//DO
SOMETHING
}
}
Apex Triggers in Salesforce
Reviewed by dasfrogpractice
on
12:03
Rating:
Neat explanation and comparative approaches of bad, good, better, best
ReplyDelete