All requests are delimited by the trigger, class method, Web Service, Visualforce page or anonymous block that executes the Apex code. If the entire request completes successfully, all changes are committed to the database. For example, suppose a Visualforce page called an Apex controller, which in turn called an additional Apex class. Only when all the Apex code has finished running and the Visualforce page has finished running, are the changes committed to the database. If the request does not complete successfully, all database changes are rolled back.
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.
The following limitations apply to generating savepoint variables and rolling back the database:
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.
The following is an example using the setSavepoint and rollback Database methods.
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);