Skip to main content

Code reviews rule: Missing controls in transactions

Written by David Martin
Updated today

Missing controls in transactions

Why is this an issue?

When performing multiple DML operations in sequence, a failure partway through can leave the database in an inconsistent state. For example, if you insert a parent record and then fail while inserting children, you end up with an orphaned parent.

Savepoints allow you to rollback to a known good state if an error occurs.

Examples

Example of incorrect code:

public void createOrderWithItems(Order ord, List<OrderItem> items) {
insert ord;
// If this fails, the Order exists without items
insert items;
}

Example of correct code:

public void createOrderWithItems(Order ord, List<OrderItem> items) {
Savepoint sp = Database.setSavepoint();
try {
insert ord;
for (OrderItem item : items) {
item.OrderId = ord.Id;
}
insert items;
} catch (Exception e) {
Database.rollback(sp);
throw e;
}
}

How can I fix violations?

  1. Create a savepoint: Call Database.setSavepoint() before the first DML operation.

  2. Use try-catch: Wrap DML operations in a try-catch block.

  3. Rollback on failure: Call Database.rollback(savepoint) in the catch block.

  4. Re-throw the exception: After rollback, re-throw or handle the exception appropriately.

When should I disable this rule?

You may dismiss specific violations when:

  • Each DML operation is independent and partial completion is acceptable

  • The operations are already wrapped in a higher-level transaction control

Resources

Did this answer your question?