11

When something wents wrong in my synchronous trigger do I have to manually take care of this by before making a Database.setSavepoint() and rollback in the catch statement?

Or is Salesforce.com automatically taking care of this in triggers?

I have found so my code examples where people manually set Savepoints that I don't get a good felling when and when NOT to use it.

13

The reason to use Savepoints and Database rollbacks is when you are doing multiple operations in a single transaction, and want to "roll-back" the entire sequence of operations if there was an exception or problem later on in the process --- e.g., after prior DML operations had been successfully committed, or after a callout was processed, etc. Now, a Database.rollback CANNOT stop a callout from having been processed by an external server, but it CAN "undo" a whole bunch of DML operations all at once, which can be VERY complicated to do when you're doing Updates or Upserts --- without Rollbacks/Savepoints, you'd have to save all of your "initial" state records, as well as your modified versions, and then manually reconcile. Rollbacks/Savepoints save you from this hassle.

For instance, suppose that I want to programmatically create a new Account, Contact, and a Case record, all in a single transaction. BUT, if there is any error creating ANY of these, then I do not want ANY of these records to be saved. Without using Savepoints and Rollbacks, you would have to do a whole bunch of DELETES, checking along the way to ensure that everything saved successfully, since, if the Account record saves, it is SAVED, regardless of whether the Contact and Case save. With Savepoints and Rollbacks, though, you can ensure that NOTHING gets saved, if there's ANY errors, without doing a bunch of conditional checks and DELETES.

WITHOUT Savepoints

Account newAccount = new Account(Name='ACME Widgets');
Contact newContact = new Contact(FirstName='Murgatroid', LastName='Bullroarer');
Case newCase = new Case(
    Status = 'New',
    Priority = 'Normal',
    Subject = 'Broken Generator'
);

try {
   insert newAccount;
   // Now that our Account has saved,
   // set our COntact's AccountId
   newContact.AccountId = newAccount.Id;
   insert newContact;
   // Now that our Contact is saved,
   // set our Case's ContactId and AccountId
   newCase.AccountId = newAccount.Id;
   newCase.ContactId = newContact.Id;
   insert newCase;

} catch (Exception ex) {

  // Undo all of the inserts we may/may not have done
  // (a total waste of DML statements, considering the alternative with Savepoints)
  // We don't need to worry about the newCase having failed,
  // as it is the last in the sequence.
  if (newContact.Id != null) delete newContact;
  if (newAccount.Id != null) delete newAccount;

  // Add a page error / send an email / debug, something
  ApexPages.addMessages(ex);
}

WITH Savepoints

// Define the Database 'point' or 'state' to which we want to rollback
// if there are ANY errors throughout our transaction

Account newAccount = new Account(Name='ACME Widgets');
Contact newContact = new Contact(FirstName='Murgatroid', LastName='Bullroarer');
Case newCase = new Case(
    Status = 'New',
    Priority = 'Normal',
    Subject = 'Broken Generator'
);

Savepoint sp = Database.setSavepoint();

try {
   insert newAccount;
   // Now that our Account has saved,
   // set our COntact's AccountId
   newContact.AccountId = newAccount.Id;
   insert newContact;
   // Now that our Contact is saved,
   // set our Case's ContactId and AccountId
   newCase.AccountId = newAccount.Id;
   newCase.ContactId = newContact.Id;
   insert newCase;

} catch (Exception ex) {
  // Roll the database back to before we saved ANYTHING
  Database.rollback(sp);
  // Add a page error / send an email / debug, something
  ApexPages.addMessages(ex);
}
| improve this answer | |
  • well the question was specific to triggers which I believe automatically rollback if an exception is thrown correct? – Phil B Aug 5 '15 at 19:21
7

If an exception occurs, the transaction is automatically rolled back.

However if you specify an explicit false when using a Database method such as Database.update(acctList, false) - then the allOrNone behaviour is overridden, and a partial commit is allowed to happen.

The optional opt_allOrNone parameter specifies whether the operation allows partial success. If you specify false for this parameter and a record fails, the remainder of the DML operation can still succeed. This method returns a result object that can be used to verify which records succeeded, which failed, and why.

You generally use SavePoints when you want to ensure atomicity over a bunch of operations - eg you may have updated a record, and then made a callout to an external system - if the external system returns failure, and you want to roll back the transaction on salesforce, you would set a savePoint before the update and roll back to that.

| improve this answer | |
  • 1
    techtrekker: So this means the only reason for a manual save and rollback is when I want to make partial commits possible? I have found so my code examples where people manually set Savepoints that I don't get a good felling when and when NOT to use it. – Robert Sösemann Mar 22 '13 at 11:09
  • 2
    To make partial commits possible, pass in the false parameter to a Database.xxx method. Savepoints are for when you are performing a bunch of operations, and if one operation fails, you want to restore the system to a consistent state rather than allowing them to commit independently of each other. If it is just records in a Database.update, you don't need a savepoint. Salesforce rolls back by default on failure. – techtrekker Mar 22 '13 at 11:17
  • Database methods wont cause exceptions to occur anyways.. – Kaushik Ray Sep 23 '14 at 11:07
0

If we use normal insert/update dml and not database.insert, I think any error in the trigger would automatically rollback all the previous dmls that occurred in the same transaction i.e. the same trigger.

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_transaction.htm

| improve this answer | |

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.