Transaction management with @EnableTransactionManagement in Spring application

In the tutorial JDBC transaction management in Spring, I showed you how to configure transaction management using an XML file. We can also use Java code to do this with the @EnableTransactionManagement annotation. How is it in detail? We will find out together in this tutorial!

First, I will create a new Maven project as an example:

We will use Java 17 for this project:

Spring Context and Spring JDBC are as follows:

I will use MySQL database as an example:

To compare the configuration with the XML file, in this tutorial, I also create a small banking application that allows us to transfer money from account A to account B. This transfer process will include 2 steps: deduct money from account A and add money to account B. If any exception occurs during money transfering, all operations will be rolled back. Similar to the previous post.

I also define a table with the following structure:

The AccountDAO interface and its implementation AccountDAOImpl to work with the account table, the AccountService interface and its implementation AccountServiceImpl to work with the application’s business, has the following content:

As you can see, after deducting money from account A, if the remaining amount of account A is less than $80, I will not allow the transfer anymore and throw Exception.

Now, I will create a new class to configure the application:

In this ApplicationConfiguration class, I use the @ComponentScan annotation for Spring to scan and initialize beans for all classes working with the table account that I created above. I also initialized beans for the DataSource and JdbcTemplate objects for these classes to use.

For example, now in my database, there are 2 accounts A and B with the following information:

Now I will write code to make the transfer of 20$ from account A to account B. The content of the Application class will be as follows:

Now, if I run this application, you will see the following error:

Account A is deducted but account B does not receive money:

To enable transaction management for this application with the @EnableTransactionManagement annotation, please declare the @EnableTransactionManagement annotation and a TransactionManager bean in the application’s configuration class:

and annotate the transfer() method of the AccountServiceImpl class with the @Transactional annotation as in the previous post:

Talking about the @EnableTransactionManagement annotation, it is equivalent to the <tx:annotation-driven/> declaration that I mentioned in the previous tutorial! This annotation has attributes that define how our application will manage transactions.

The adviceMode attribute defines how we apply aspect-oriented programming using a Java proxy, the CGLIB library, or the AspectJ library. By default, Spring uses PROXY!

Attribute proxyTargetClass used only for activeMode is PROXY and if its value is true then CGLIB library will be used. Otherwise, if the value of this attribute is false then the Java proxy will be used.

@Transactional annotation, I mentioned it to you in the previous post. The declaration of the @Transactional annotation, the class level or the method level, will help Spring know what level we need to manage the transaction.

Interface TransactionManager has 2 sub-interfaces, PlatformTransactionManager and ReactiveTransactionManager.

PlatformTransactionManager is for manipulating the database in an imperative way, and ReactiveTransactionManager is for reactive style! You can use the appropriate implementations of each of these sub-interfaces for your application. In the example of this tutorial, I am using PlatformTransactionManager with the implementation of DataSourceTransactionManager!

Update the database again so that the amount of account A is back to $ 100 and then run the application again, you will see that an error has occurred but account A is not deducted anymore!

Add Comment