0

I am playing around with Database.setSavePoint() in a trigger. I put it at the top of my BeforeUpdate method and then I roll back at the end of the method.

Then I try to modify an Opportunity record in Salesforce through the UI and save. The record gets saved correctly when I thought it shouldn't?

I have never used savepoints in a trigger before so I wonder if there's something that I am missing?

Here's a code snippet.

Trigger:

trigger OpportunityMainTrigger on Opportunity(before insert,before update, before delete,after insert ,after update,after delete) {
    TriggerDispatcher.Run(new OpportunityTriggerHandler());
}

Trigger Dispatcher:

public class TriggerDispatcher{
    /*
        Call this method from your trigger, passing in an instance of a trigger handler which implements ITriggerHandler.
        This method will fire the appropriate methods on the handler depending on the trigger context.
    */
    public static void Run(ITriggerHandler handler){
        // Check to see if the trigger has been disabled. If it has, return
        //if (handler.IsDisabled())
           // return;

        // Detect the current trigger context and fire the relevant methods on the trigger handler:

        // Before trigger logic
        if (Trigger.IsBefore ){
            if (Trigger.IsInsert)
                handler.BeforeInsert(trigger.new);

            if (Trigger.IsUpdate)
                handler.BeforeUpdate(trigger.newMap, trigger.oldMap);

            if (Trigger.IsDelete)
                handler.BeforeDelete(trigger.oldMap);
        }

        // After trigger logic
        if (Trigger.IsAfter){
            if (Trigger.IsInsert)
                handler.AfterInsert(Trigger.newMap);

            if (Trigger.IsUpdate)
                handler.AfterUpdate(trigger.newMap, trigger.oldMap);

            if (trigger.IsDelete)
                handler.AfterDelete(trigger.oldMap);

            if (trigger.isUndelete)
                handler.AfterUndelete(trigger.oldMap);
        }
    }
}

TriggerHanlder:

public class OpportunityTriggerHandler implements ITriggerHandler{
    public void BeforeUpdate(Map<Id, SObject> newItems, Map<Id, SObject> oldItems){
        Savepoint saveP = Database.setSavePoint();
        try {
            // some code
            Database.rollback(saveP);
        } catch (Exception ex) {
           // some code
        }
     }
}
7

The savepoint specifies the point to roll back to. All DML that occurs between setting the savepoint and performing the rollback is included in the rollback.

If you did an update someAccount; inside your try block, you'd see the effect of that DML operation be rolled back.

But that doesn't include the trigger event that started the whole process. The DML update that initiated the trigger's firing took place prior to the savepoint. If you want to roll it back, you'd have to fail the transaction by doing addError() or throwing an unhandled exception. Here, you're actually catching exceptions, which will prevent a rollback of the entire transaction from occurring based on errors that take place inside the try block (other than uncatchable exceptions, like LimitException and UnexpectedException).

The reference documentation here is Transaction Control.

Apex gives you the ability to generate a savepoint, that is, a point in the request that specifies the state of the database at that time. Any DML statement that occurs after the savepoint can be discarded, and the database can be restored to the same condition it was in at the time you generated the savepoint.

(Emphasis mine).

  • Love your explanation, this makes complete sense now! – Arthlete Jun 11 at 18:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.