How to Manage Transactions in Salesforce Apex?

💡 Recommendation: Watch the video tutorial below before reading.

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 allOrNone parameter 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, and Database.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.