Transaction Management in Spring Data

Eralp Onay
Yıldız Tech
Published in
4 min readSep 5, 2023

Today we will discuss transaction management in Spring and how Spring makes it easier for us with Transactional annotation.

Transaction management is the process that has a series of related operations either succeed in their entirety or fail as a single atomic unit. In the context of databases, transactions ensure data consistency and prevent data corruption or data loss due to concurrent access or application failures.

Right from the 1.0 version, Spring offered support for AOP-based transaction management that allowed developers to define the transaction boundaries, and right after that Spring added Transactional annotation.

What is precisely Transactional annotation?

The @Transactional is a key feature of Spring Framework that simplifies transaction management. You might specify the boundaries of transactions and delegate the responsibility of transaction handling to Spring. When you use Transactional annotation Spring automatically creates a transaction around the annotated code and manages the transaction lifecycle.

The @Transactional is metadata that specifies that an interface, class, or method must have transactional semantics; for example, "start a brand new read-only transaction when this method is invoked, suspending any existing transaction". The default @Transactional settings are as follows:

  • Propagation setting is PROPAGATION_REQUIRED.
  • Isolation level is ISOLATION_DEFAULT.
  • ReadOnly is false.
  • Transaction timeout defaults to the default timeout of the underlying transaction system, or to none if timeouts are not supported.
  • Any RuntimeException triggers rollback, and any checked Exception does not.

For more detailed information about default settings, you can use the link.

Before we dive deep into how to implement Transactional annotation we need to explain some of the key concepts :

Transaction Propagation : The @Transactional annotation supports different propagation types, which determine how transactions should behave when multiple methods are invoked within the same transactional context. Propagation types like:

  • REQUIRED: The method joins an existing transaction or creates a new one if none exists.
  • REQUIRES_NEW: The method always creates a new transaction, suspending any existing transaction if present.
  • SUPPORTS: The method participates in an existing transaction if available, but otherwise, it executes non-transactionally.
  • NOT_SUPPORTED : If a transaction exists, first Spring suspends it, and then the business logic is executed without a transaction
  • MANDATORY : If there is an active transaction, then it will be used. If there is not, Spring throws an exception
  • NEVER : Spring throws an exception if there’s an active transaction
  • NESTED : Spring check for a transaction and if it exists Spring save that transaction point, let s assume there is an exception then the transaction rollbacks to this point. If there’s no active transaction, it works like REQUIRED propagation.

Isolation Level : The isolation level of a transaction defines of which data being access is isolated from other concurrent transactions. Isolation levels like:

  • READ_UNCOMMITTED: Allows a transaction to read uncommitted changes made by other transactions (lowest isolation level).
  • READ_COMMITTED: Allows a transaction to read only committed changes made by other transactions (default isolation level).
  • REPEATABLE_READ: Provides a consistent read of the same data within the same transaction.
  • SERIALIZABLE: Ensures the highest level of isolation, preventing concurrent access to the same data.

Rollback Rules : The @Transactional annotation allows you to specify which exceptions should trigger a rollback of the transaction using the rollbackFor attribute. By default, the transaction will be rolled back for unchecked exceptions.

The @Transactional also supports the timeout attribute, allowing you to set a timeout for the transaction. If the specified time is exceeded, the transaction will be automatically rolled back.

How to use @Transactional in Spring Boot?

Let s see a simple example of transactional annotation and use its features how to manage transactions and their boundaries.

When Spring initializes the application context, it scans for beans with @Transactional annotations. For each annotated method, Spring creates a proxy around the original bean. This proxy intercepts method calls, allowing Spring to apply transactional behavior without altering the actual business logic implementation.

Here is an example of how to change the transaction’s isolation level :

@Transactional(isolation = Isolation.SERIALIZABLE)

Propagation type definition :

@Transactional(propagation = Propagation.SUPPORTS)

Now let s dive into the rollback feature a little bit and here is an example of it :

You can specify which class would trigger the rollback with this. If you just use Transactional annotation by default, transactions are rolled back for unchecked exceptions (RuntimeException and its subclasses). However, with the rollbackFor attribute of @Transactional, you can specify custom rollback rules, indicating which exceptions should trigger a rollback.

In this example, you prevent rollback for specific classes due to noRollbackFor attribute.

Conclusion

The @Transactional annotation in Spring offers a powerful solution for managing transactions. Using transaction management, developers can simplify their code, improve maintainability, and ensure data consistency with minimal effort. Understanding the concepts and capabilities @Transactional ensures that developers might create more robust and efficient applications.

--

--