Skip to content

Overview

available in v6.0

Backendless Database can execute multiple database requests grouped into a single transaction. When any one of these grouped database operations fails, the entire transaction is rolled back - meaning any other changes within the same transaction are canceled. Client applications and Backendless cloud code (business logic) can use this functionality via Transaction API, which is described within this section of the API documentation.

A single transaction can include multiple create, update, delete, retrieve and relation management (set/add/delete) operations. The result of an operation can be used as an input parameter in any of the subsequent ones. Consider the example below. The example stores an object in a table and then creates a relation between that object and some other ones identified with a query from another table:

// create a UnitOfWork instance - it represents a transaction and
// will accumulate all operations in it.
UnitOfWork *uow = [UnitOfWork new];

// Create a person object
NSDictionary *person = @{@"name": @"Joe", @"age": @20};

// add a "create" operation to the transaction
// notice the result object will be reused later on
OpResult *createPersonResult = [uow createWithTableName:@"Person" objectToSave:person];

// add an operation to create a relation. This operation uses
// the result from the previous "create" operation
[uow setRelationWithParentResult:createPersonResult
                      columnName:@"visitedCountries"
          whereClauseForChildren:@"name = 'China'"];

// execute the transaction.
[uow executeWithResponseHandler:^(UnitOfWorkResult *result) {
    NSLog(@"Is transaction successful - %i", result.isSuccess);
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
// create a UnitOfWork instance - it represents a transaction and
// will accumulate all operations in it.
let uow = UnitOfWork()

// Create a person object
let person = ["name": "Joe", "age": 20] as [String : Any]

// add a "create" operation to the transaction
// notice the result object will be reused later on
let createPersonResult = uow.create(tableName: "Person", objectToSave: person)

// add an operation to create a relation. This operation uses
// the result from the previous "create" operation
let _ = uow.setRelation(parentResult: createPersonResult,
                        columnName: "visitedCountries",
                        whereClauseForChildren: "name = 'China'")

// execute the transaction.
uow.execute(responseHandler: { result in
    print("Is transaction successful - \(result.isSuccess)")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

There are several benefits for using transactions:

  • If any of the operations fail, the entire transaction is rolled back - there is no need to perform any clean up from your code.
  • From the client-side perspective there is only one request going to the server - the request to execute the transaction. For instance, the example above performs two operations: (1) saving an object in the database and (2) establishing a relationship between the saved object and others identified with a query. However, the client application sends only one request to the server.
  • Consistency and referential integrity - transactions ensure that there is no "dirty data" in your database. This helps with keeping your client-side code cleaner and the data consistent.

Backendless transactions rely on the following concepts:

  • Unit of Work - is a special class in the SDK which combines multiple individual database operations into a single object. All operations added to a unit of work have a sequence number and will be executed on the server side in the same order they were added. A unit of work essentially represents a transaction; For more information see the Unit of Work section of this guide.
  • Database Operation - a single operation executed within a transaction. This can be either create, retrieve, update, delete and relation management (create, update, delete) operation;
  • Operation Result - an entity representing the result of an individual database operation. The result of one operation can be referenced in other subsequent operations. You can see an example of it in the sample code shown above. For example, a "create" operation returns a result. The result represents the object saved in the database. That object may be referenced in an operation to set a relationship for the object. Alternatively, you can "extract" a value of a specific property from the operation result and also use it in other operations in the same transaction.

The diagram below illustrates these concepts as they relate to each other:

unitofwork-diagram