Transaction API Support for Codeless
The purpose of transactions is to protect your data from partial database updates that fail to be complete. The Transaction API is now available for Codeless.
With the Transaction API, our 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.
Until now, the Transaction API was limited to Backendless users building with code. Now, the API is available for Codeless developers as well.
The following section describes how the Transaction API works and some of its many benefits. Then, we will provide an example featuring the Codeless Transaction API.
Benefits of Transactions
So, what does the transaction API do for you? Let’s look at some of the benefits.
- Firstly, if any of the operations fail, the entire transaction is rolled back – there is no need to perform any clean-up from your code. In other words, no permanent changes are made to your database that would need to be fixed if an operation fails.
- Next, from the client-side perspective, there is only one request going to the server – the request to execute the transaction. For instance, say a transaction 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. With the Transaction API, the client application sends only one request to the server.
- Third, transactions provide consistency and referential integrity for your database. In other words, transactions ensure that there is no “dirty data” in your database. This helps keep your client-side code cleaner and the data consistent.
How the Transactions API Works
Backendless transactions rely on the following concepts:
- Unit of Work – is the entire payload of the transaction request 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 the documentation.
- Database Operation – a single operation executed within a transaction. This can be either a 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.
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” the 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:
Unit of Work API
The heart of the Backendless Transactions API is a request called
UnitOfWork. It is used by client applications to compose a transaction.
Composing a transaction means adding various database operations to a unit of work. The “Find” operation, for retrieving objects from your database, is shown above. These operations may be “linked” to each other by using the output/result on one operation as the input for another. For example, in the block below, we see an example of an “Update” operation with the option to refer to a previous operation in the transaction.
When the server receives a
UnitOfWork request, it starts processing its operations. The server executes all operations one by one in the context of a single database transaction.
If any of the operations fails, Backendless rolls back all the changes and returns the information about the result of each operation to the client. However, if all operations succeed, the entire database transaction is committed. This means the data will be finalized in the database.
Using Backendless Transaction API, you can configure an isolation level for your transaction. The isolation level determines how the Backendless database separates your transaction from all others running at the same time.
Without any isolation, one transaction could modify the data another transaction is reading and, by doing so, data inconsistency would be created. Isolation levels determine how isolated your transaction is from others. This is implemented by applying a lock on the data retrieved in a transaction. Different levels of isolation imply different locking mechanisms, each of which also yields various data read phenomena.
One of the most powerful elements of the Transaction API is the ability to use the result of an operation in other subsequent operation(s) within the same transaction. This is made possible by a “protocol” that all transactional operations follow: every operation can have a unique identifier.
The identifier can be used in another operation to reference the result from the operation where it was used. This allows for a “chaining effect” where data comes out of one operation and is then fed into another. Consider the example below. The example saves a new object in the database and then establishes a relationship between the created object and objects in another table.
The operation to save the object in the database assigns a unique ID to each operation. This ID is then used in the subsequent operation to establish a relationship between the object and its children.
We are going to walk through the following Codeless transaction to break down what is happening in each step. This Codeless block is being used to store details of a purchase. Below, we walk through each step of this API call.
For reference, the table schemas for the two tables in this example are found below. Here’s a breakdown of each step of this API service:
- First, for this example, we are going to create an API Service called
TransactionsDemowith the Method name
createObjectsSaveRelation. You do not have to create a new API Service to run the logic in this example; all of the following steps can be used in almost any Codeless logic you create.
- Next, we create a variable
myTxand set its contents to be a new transaction. The isolation for the transaction is set to “Repeatable read”.
- This is the “wrapper” for your transaction. Here, we implement the operations that make up the transaction (or
myTx. Note: Keep in mind, order matters. Particularly if you have operations that are dependent on another operation in the same transaction, you will need to be sure you put your operation steps in the right order to achieve your desired result.
- As the first operation in our transaction, we perform a “Create” operation named
createOrderOp. This operation creates an object with
orderId = 061821-CV1and
amount = 189.2in the
- For the second operation, we perform a “Bulk Create” operation and name it
createOderItemsOp. In this operation, we create two data objects –
quantity = 10and
quantity = 20. These items are added to the table
- Finally, we perform a “Set Relation” operation to connect our children data objects to our parent. We don’t need to give this operation a name (id). For the parent, we are accessing the
Ordertable. The parent object is then found by accessing the result of the
createOrderOpoperation. The column we are creating a relation to is called
orderDetails. To find the children options, we will again access the result of a previous operation. This time, it’s the
The result of this API call will be:
Order table schema:
OrderItem table schema:
Thanks for reading and Happy Codeless Coding!
Credit: Source link