How to manage transactions in Spring boot using annotations

Dushan Devinda
Chain Analytica
Published in
5 min readNov 7, 2019

What is Spring boot?

Spring boot is a java based open-source framework built on top of spring. This platform eliminates the complex XML configuration in spring and provides easily maintainable microservices-based architecture.

The above diagram depicts the main architecture of a spring boot application.

The service layer handles all the business logic in your application, while the controller provides the space to develop rest endpoints for your application. Repository handles all the database related operations (CRUD operations). The model handles the objects that we use in our application.

What is a transaction?

A transaction is a logical unit of processing in a DBMS that access and modify (read and update) the content of a database. This transaction can be a single command, a piece of command and these may take part in any other database operations.

A bank transaction between two people would be an excellent example of a transaction. In this example, we can see there are several tasks in a single transaction like checking the balance of person X, deduct the amount to be transferred to person Y, add the amount to person Y’s account.

The above transaction should be managed successfully in real life to complete the transaction and the same should result in the database too. For maintaining the integrity of data, the DBMS systems have to ensure ACID properties. ACID stands for Atomicity, Consistency, Isolation and Durability.

Atomicity — Since the transaction is treated as a single unit of operation, the transaction should be executed entirely or do not execute it at all. There can not be any partial execution. In another word, this is described as ‘all or nothing’ property.

Consistency — When a transaction is completed, the database should remain in a consistent state. This refers to the correctness of a database.

Isolation — Transactions occur independently without interference (execute in isolation from other transactions). Incomplete transactions will not be visible to other transactions going on concurrently.

Durability — When a transaction completes successfully, it should permanently record in the database even if the system fails or restarts.

How we define transactions in our Spring boot project?

Defining transaction in spring boot is simple. You only have to put @Transactional annotation on your class or method. But where should we put it in your Data Access Object or Service layer?

  • Data Access Object is an object or an interface that encapsulates the logic for retrieving, saving and updating data in your data storage.
  • The service layer represents the business logic.

We need to put a transactional annotation in the service layer since it may call different DAOs to perform DB operations. There may be functions that have more than one DAO operations and if one of those DAO operations failed, the database would go to an inconsistent state. Using your transactional annotation in the service layer will bypass these types of situations. If the DAO operations are transactional and if you have more than one DAO operation calls in a single service method, then you would have multiple transactions for a single function. This is not the best way because of these things we use transactional annotation in the service layer.

All right, let’s go to an example and see how this works. For demonstration purposes, I created a demo database and two tables named user_one and user_two. Down below, you can see the structure of two tables.

In the user_two table, I’ve defined the email column as “Not Null” and if we try to add a null value to that using our spring boot application, it will give us an error.

Scenario 1

In this scenario, we try to update two tables without using transactional annotation. First, we upload one record to user_one and then we upload one record to user_two. But when we upload to user_two, we try to populate an error by uploading a null value to the email column which can not be null.

When we run the above function, we get an exception saying we have uploaded a null value for our not null column. But when you check the database, we can see that the first SQL operation, which was an insertion for user_one has completed and updated the table successfully while the second SQL operation has not completed and updated the table successfully.

Scenario 2

In this scenario, I add the transactional annotation to our function and do the same process (with different values for records).

When we run the above function, the same exception occurred, but unlike the previous scenario, both SQL transactions have not completed and updated the tables successfully.

When we check the database, we can see previously added records are only there in the table. There is no record with the username of “Bob” in the user_one table or “Jane” in the user_two table.

That means the database is in a consistent state. Here we can see ACID properties in action.

--

--