+ Start a Discussion
SFDC_LearnerSFDC_Learner 

SavePoint and Rollback

Savepoint sp = Database.setSavepoint();

 

Database.rollback( sp );

 

 

Can you tell me what is the advantage of above statements, plz give a small ex to understand this.

MagulanDuraipandianMagulanDuraipandian

https://sites.google.com/site/infallibletechie/what-is-database-savepoint-in-salesforce3

 

check this...

 

 

Regards,

Magulan D

Salesforce.com certified Force.com Developer.

SFDC Blog

SFDC Site

If this post is your solution, kindly mark this as the solution and give Kudos.

asish1989asish1989

HI 

Savepoint and roll back will help us to create your own transcation. Suppose you  have written long code which contains many more DML statement, at the some point you will want this DML statement should not be executed, you may need to modify your code, at that time you will have to return that point, savepoint will identifies that point , Rollback will  restore the database to that point(savepoint).

Here is some code you can refer

Account a = new Account(Name = 'xxx'); insert a;
   System.assertEquals(null, [SELECT AccountNumber FROM Account WHERE Id = :a.Id].
                              AccountNumber);

   // Create a savepoint while AccountNumber is null
   Savepoint sp = Database.setSavepoint();

   // Change the account number
   a.AccountNumber = '123';
   update a;
   System.assertEquals('123', [SELECT AccountNumber FROM Account WHERE Id = :a.Id].
                                AccountNumber);

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

 Did this post answers your question,if so please mark it solved

 

   Thanks

 

 

Rahul SharmaRahul Sharma

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);
}

 

SFDC_LearnerSFDC_Learner

Thanku

Abhiram RogerAbhiram Roger
HI Rahul,

Would this happen automatically since you are inserting both parent and child in the same transaction. So if there is a failure, the previous successful dml should automatically rollback, right?
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_transaction.htm
docbilldocbill
Hi Abhiram,

I realise you asked this almost two years ago, so I am mainly answering for anyone else looking this up.  Whether the rollback happens automatically depends on context.   For example.
 
private void updateParentAndChild()
    update parent;
    update child;
}

If you transaction called updateParentAndChild without ever catching exceptions, then yes,  a failed update to child would rollback the parent.  But if instead you caught the exception then it is your resposibility to rollback the transaction.  Here is an actual code sample:
 

    /**
     * Called to upsert a list of records, while allowing field truncation. Setting the dml options on
     * individual records does not work, so we have to emulate an upsert by doing an insert and update.
     * This means we use an extra DML operation and we return save results instead of upsert results.
     * 
     * @param upsertList
     * @param throwErrors true if an exception should be thrown for errors
     * @return list of save results
     */
    public static List<Database.SaveResult> upsertAllowFieldTruncation(List<SObject> upsertList, Boolean throwErrors)
    {
        List<Database.SaveResult> retval = new List<Database.SaveResult>();
        List<SObject> insertList = new List<SObject>();
        List<SObject> updateList = new List<SObject>();
        List<Integer> insertIndexList = new List<Integer>();
        List<Integer> updateIndexList = new List<Integer>();
        Integer i=0;
        for(SObject record : upsertList) {
            if(record.Id == null) {
                insertList.add(record);
                insertIndexList.add(i++);
            }
            else {
                updateList.add(record);
                updateIndexList.add(i++);
            }
            retval.add(null);
        }
        Savepoint sp = null;
        if(throwErrors && ! insertList.isEmpty() && ! updateList.isEmpty() ) {
            sp = Database.setSavepoint();
        }
        Database.DMLOptions dmo = new Database.DMLOptions();
        dmo.allowFieldTruncation = true;
        dmo.OptAllOrNone = throwErrors;
        for(Database.SaveResult r : Database.insert(insertList,dmo)) {
            retval[ insertIndexList.remove(0) ] = r;
        }
        try {
            for(Database.SaveResult r : Database.update(updateList,dmo)) {
                retval[ updateIndexList.remove(0) ] = r;
            }
            sp = null;
        }
        finally {
            if(sp != null) {
                Database.rollback(sp);
            }
        }
        return retval;
    }

Is this case I am simulating an upsert operation.  I'm using the rollback, because if the throwErrors flag is true, I want to roll back both the inserts and updates, just like a real upsert call would do.  Since this is a method in one of my utilities class, I do not want the results to depend on whether the calling method catches the exception...