What is Transactions?
In programming, we refer to a transaction as a group of related actions that need to be performed as a single action. We require this to ensure data integrity in our applications.
Warning
Use a transaction where it is needed, i.e. when updating multiple tables in an atomic operation. Wrapping all calls to the DB is not a good idea: it might lead to reduced throughput and blocking.
https://stackoverflow.com/questions/6562527/should-i-wrap-every-db-call-in-transaction
Letās have a look at an example to understand this better. A typical requirement in event-based architecture is to update the local database and produce an event for consumption by other services:

Here, weād like these two operations to either happen together or not happen at all. We can achieve this by wrapping these operations into a single transaction:

We typically refer to these components like database and message broker as participating resources in a transaction.
Operations that are part of a transaction can all execute in a single participating resource or span across multiple participating resources. Hence, transactions can be local or distributed.
- Local transaction: operations execute in the same resource.
- Distributed transaction: a transaction can involve multiple independent resources like databases, message queues, or web services. These resources can execute on the same virtual machine, on different virtual machines in the same physical machine, or different physical machines altogether.

@Transactional
Itās important to notice that JPA on itself does not provide any type of declarative transaction management. When using JPA outside of a dependency injection container, transactions need to be handled programmatically by the developer:
UserTransaction userTransaction = entityManager.getTransaction();
try {
userTransaction.begin();
businessLogic();
userTransaction.commit();
} catch(Exception ex) {
userTransaction.rollback();
throw ex;
}This way of managing transactions makes the scope of the transaction very clear in the code, but we will end up with lots of similar codes (Cross Cutting Concerns) scattered all over your project.
The codes that handle the transactions are separated from our businesses logic and will not be scattered all over our project. Itās one of the main concepts of Aspect Oriented Programming (AOP)1.
Thatās why we use @Transactional annotation to handle the transaction. This annotation includes three parts:
- Transactional aspect
- Transaction manager
- Entity manager proxy
Transactional Aspect
The Transactional Aspect is an āaroundā aspect that gets called both before and after the annotated business method. The concrete class for implementing the aspect isĀ TransactionInterceptor.
- At the ābeforeā moment, the aspect provides a hook point for determining if the business method about to be called should run in the scope of an ongoing database transaction, or if a new separate transaction should be started.
- At the āafterā moment, the aspect needs to decide if the transaction should be committed, rolled back or left running.
At the ābeforeā moment the Transactional Aspect itself does not contain any decision logic, the decision to start a new transaction if needed is delegated to the Transaction Manager.
Transaction Manager
The transaction manager needs to provide an answer to two questions:
- Should a new database transaction be started?
- Should a new
EntityManagerbe created?
If the transaction manager decides to create a new transaction, then it will:
- Create a new entity manager
- Bind the entity manager to the current thread
- Grab a connection from the DB connection pool
- Bind the connection to the current thread
Entity Manager Proxy
When the business method calls for example entityManager.persist(), this call is not invoking the entity manager directly. Instead, the business method calls the proxy, which retrieves the current entity manager from the thread, where the Transaction Manager put it.