Sunday, October 11, 2020

Transaction Control Using Database.setSavepoint and Database.rollback

In this article we are going to understand and implement transaction control using Database class methods setSavePoint and rollback which help to restore and rollback the partial work i.e already executed DML statements in a apex transaction. 


Sometimes during the processing of records, your business rules require that partial work (already executed DML statements) be “rolled back” so that the processing can continue in another direction. 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.

Database.setSavepoint() is used to define a point at which DML operations can be rolled back. If any error occurs during DML Operations, that contains many statements, the application will be rolled back to the most recent save point and the entire transaction will not be aborted.

Let's see an example below to understand this:

Account acc = new Account(Name = 'Salesforce Learning Hub'); insert acc;

//Since we didn't provided the AccountNumber, it will be null

System.assertEquals(null, [SELECT AccountNumber FROM Account WHERE Id = :acc.Id]. AccountNumber); // Create a savepoint while AccountNumber is null Savepoint sp = Database.setSavepoint(); // Saveponit created here

// Change the account number acc.AccountNumber = '123'; update acc;

//Now account is updated with Account Number 123

System.assertEquals('123', [SELECT AccountNumber FROM Account WHERE Id = :a.Id]. AccountNumber); // Rollback to the previous null value Database.rollback(sp);

//Code is rollbacked to savepoint which means account number that we updated will

be rolled back

System.assertEquals(null, [SELECT AccountNumber FROM Account WHERE Id = :a.Id]. AccountNumber);


See one more example below: 

Suppose, There is a scenario where you insert parent with child record from visualforce page.

Case 1 : Unfortunately there was any error in creating child record(like user didn't fill required fields), but parent has been created successfully.

Case 2 : User has filled the required information and clicked on save button again. So in this case there will be two parents created.

Now if you look into data base, there will be two parent records (from case one with no child and from case 2 with a child).

So case one could be avoided by using savepoint and rollback.

The syntax is to set the save point before any dml and then rollback to that savepoint when you face any error.
Savepoint sp = Database.setSavepoint();
try{ insert parent; insert child;
catch(exception ex){
Database.rollback(sp);     }
}
One more example below:
Savepoint sp = Database.setSavepoint();; Account a = new Account(); a.Name='Salesforce Learning Hub'; a.AccountNumber = '123'; insert a; Contact c = new Contact()
c.Account = a.Id; try { insert c; } catch(Exception e) { Database.RollBack(sp); }
In this example, if any error occurs while inserting the Contact 'c', then the entire transaction will be rolled back to savepoint sp ( as specified in the catch section by Database.rollback method).

Some points that needs to be considered:

1) If you set more than one savepoint, then roll back to a savepoint that is not the last savepoint you generated, the later savepoint variables become invalid. For example, if you generated savepoint SP1 first, savepoint SP2 after that, and then you rolled back to SP1, the variable SP2 would no longer be valid. You will receive a runtime error if you try to use it.

2) References to savepoints cannot cross trigger invocations because each trigger invocation is a new trigger context. If you declare a savepoint as a static variable then try to use it across trigger contexts, you will receive a run-time error.

3) Each savepoint you set counts against the governor limit for DML statements.
4) Static variables are not reverted during a rollback. If you try to run the trigger again, the static variables retain the values from the first run.

5) Each rollback counts against the governor limit for DML statements. You will receive a runtime error if you try to rollback the database additional times.

6) The ID on an sObject inserted after setting a savepoint is not cleared after a rollback. Create an sObject to insert after a rollback. Attempting to insert the sObject using the variable created before the rollback fails because the sObject variable has an ID. Updating or upserting the sObject using the same variable also fails because the sObject is not in the database and, thus, cannot be updated.

For more reference please visit:

No comments:

Post a Comment

Fan Switch Example | Understanding Communication between Lightning components

In this article we are going to see a simple FAN switch on/off example. Concept used here are: 1) Parent to child communication using Aura M...