Managing transactions in Salesforce Apex is crucial for maintaining data integrity, error handling, and system reliability. Apex executes code in a single transaction by default, meaning all operations succeed or fail together. However, Salesforce provides several mechanisms to control transaction behavior.
Now let’s learn them one by one.
1. Default Behavior
- Salesforce automatically rolls back all database operations in the transaction in case of an unhandled exception.
- If any DML operation fails (due to validation rules, triggers, or other errors), the entire transaction is rolled back.
2. Using Try-Catch Blocks
- By catching exceptions, we can decide whether to roll back a transaction, log errors, or take alternative actions, ensuring data integrity and robust error handling.
- It can be combined with savepoints and database methods or normal DML operations.
- Use specific exception types (e.g.,
DmlException,QueryException) for precise handling, rather than the generic Exception class, to differentiate between error types. - Be careful of DML and SOQL limits within try-catch blocks, as each operation counts toward the 150 DML statements or 100 SOQL query limits.
3. Using sObjects
- You can use this to avoid partial success in try catch.
- Perform common DML operations in one go to multiple objects.
- Help reduce DML count.
- Automatically Rolls back all database operations in the transaction in case of an unhandled exception.
4. Using Database Methods with Partial Success
- Apex provides Database class methods (e.g.,
Database.insert,Database.update,Database.delete) that offer fine-grained control over DML operations. - Setting the
allOrNoneparameter to false allows partial success, where valid records are committed even if some fail. - This approach is useful for bulk operations where you want to process as many records as possible, even if some fail.
5. Using Savepoints and Rollbacks
- developers to set a point in a transaction to which they can revert if an error occurs.
- The
Database.setSavepoint()method creates a savepoint, andDatabase.rollback(savepoint)reverts the database to that point. - It is ideal for scenarios where you need to undo specific operations while keeping earlier changes intact or for complex logic requiring partial rollbacks.
Example Code
Create a class named “TranManage”.
public class TranManage {
// 1. Default Behavior
public static void defaultBehaviour(){
Account acc = new Account(Name = 'Default Behavior');
Contact con = new Contact(LastName = 'Test-0');
insert acc;
insert con;
}
// 2. Using Try-Catch Blocks
public static void tryCatchBlocks(){
Account acc = new Account(Name = 'Using Try-Catch Blocks');
Contact con = new Contact( FirstName = 'Test-1');
try{
insert acc;
insert con;
} catch (Exception ex){
system.debug('Baby Chicken!');
}
}
// 3. Using sObjects
public static void usingSObjects(){
List<Sobject> objList = new List<sobject>();
Account acc = new Account(Name = 'Using sObjects');
Contact con = new Contact( FirstName = 'Test-2');
objList.add(acc);
objlist.add(con);
insert objList;
}
// 4. Using Database Methods with Partial Success
public static void databaseMethods(){
List<Sobject> records = new List<Sobject>();
records.add(new Account(Name = 'Using Database Methods with Partial Success'));
records.add(new Contact(LastName = 'Test-3'));
Database.SaveResult[] saveResultList = Database.insert(records, true);
}
// 5. Using Savepoints and Rollbacks
public static void savepointsAndRollbacks(){
Account acc = new Account(Name = 'Using Savepoints and Rollbacks');
Contact con = new Contact( FirstName = 'Test-4');
SavePoint sp = Database.setSavePoint();
try{
insert acc;
insert con;
} catch (Exception ex){
Database.rollback(sp);
system.debug('Baby Chicken!');
}
}
}
Now, Test it in anonymous window
insert new Account(Name = 'Welcome 0!');
TranManage.defaultBehaviour();
insert new Account(Name = 'Welcome 1!');
TranManage.tryCatchBlocks();
insert new Account(Name = 'Welcome 2!');
TranManage.usingSObjects();
insert new Account(Name = 'Welcome 3!');
TranManage.databaseMethods();
insert new Account(Name = 'Welcome 4!');
TranManage.savepointsAndRollbacks();
Best Practices
- Always handle exceptions gracefully to avoid unexpected rollbacks.
- Use Database methods with partial success for bulk operations.
- Implement savepoints for complex transactions requiring selective rollback.
- Monitor governor limits when using multiple DML or SOQL operations.
Conclusion
Managing transactions in Apex ensures data consistency and error resilience. By leveraging try-catch blocks, Database methods, savepoints, and bulk DML strategies, developers can build robust and scalable Salesforce applications.