A Guide to Transaction Management in Java and the Spring Framework
Aug 01, 2025 am 06:25 AMSpring's @Transactional only rolls back for RuntimeException by default. 2. It is necessary to specify that exceptions are also rolled back through rollbackFor. 3. The propagation behavior REQUIRED is the default value. REQUIRES_NEW will suspend the current transaction. 4. The self-call will cause the transaction to fail due to proxy failure. 5. It is recommended to use declarative transactions at the service layer and maintain short transactions to improve performance. Finally, the transaction behavior should be verified through tests to ensure data consistency.
Managing transactions properly is cruel for maintaining data integrity in Java applications, especially when working with databases. In enterprise applications, a transaction typically involves multiple operations that must all succeed—or, if any fail, everything must roll back to maintain consistency. Java and the Spring Framework provides powerful tools to handle transaction management effectively. Here's a practical guide to understanding and implementing transaction management in Java and Spring.

1. What Is Transaction Management?
A transaction is a sequence of operations performed as a single logical unit of work. It must satisfy the ACID properties:
- Atomicity : All operations in the transaction succeed or fail together.
- Consistency : The database remains in a consistent state before and after the transaction.
- Isolation : Concurrent transactions don't interfere with each other.
- Durability : Once committed, changes are permanent.
In Java, transaction management can be handled either programmatically (with explicit control) or declaratively (using annotations or configuration), with Spring favoring the latter.

2. Transaction Management in Plain Java (JDBC)
Before Spring, raw JDBC was commonly used, where transactions were managed manually using Connection
objects.
Connection conn = dataSource.getConnection(); try { conn.setAutoCommit(false); // Start transaction // Perform DB operations jdbcTemplate.update("UPDATE accounts SET balance = balance - ? WHERE id = ?", 100, 1); jdbcTemplate.update("UPDATE accounts SET balance = balance ? WHERE id = ?", 100, 2); conn.commit(); // Commit if all succeed } catch (Exception e) { conn.rollback(); // Rollback on error throw e; } finally { conn.setAutoCommit(true); conn.close(); }
Issues with manual JDBC transactions :

- Error-prone (easy to forget rollback or close).
- Boilerplate code.
- Hard to maintain and test.
This is where Spring's abstraction becomes valuable.
3. Spring's Transaction Abstraction
Spring provides a consistent transaction model that supports both programming and declarative transaction management, abstracting away the underlying transaction API (JDBC, JPA, JTA, etc.).
Key Components:
-
PlatformTransactionManager
: The core interface (eg,DataSourceTransactionManager
,JpaTransactionManager
). -
@Transactional
: Annotation for declarative transaction demarcation. -
TransactionTemplate
: For programmatic control.
4. Declarative Transaction Management with @Transactional
This is the most common and recommended approach in Spring.
Step 1: Enable Transaction Management
Add @EnableTransactionManagement
to your configuration class (usually not needed in Spring Boot, as it's auto-configured).
@Configuration @EnableTransactionManagement public class TransactionConfig { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
Step 2: Use @Transactional
on Service Methods
@Service public class BankService { @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void transferMoney(long fromId, long toId, double amount) { jdbcTemplate.update("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, fromId); jdbcTemplate.update("UPDATE accounts SET balance = balance ? WHERE id = ?", amount, toId); // If an exception occurs, both updates are rolled back } }
How It Works:
- Spring creates a proxy around the
BankService
bean. - When
transferMoney()
is called, the proxy starts a transaction. - If the method completes normally → transaction commits.
- If a checked or unchecked exception is thrown → transaction rolls back (by default, only for unchecked exceptions).
5. Understanding @Transactional
Behavior
@Transactional
has several attributes to fine-tune behavior:
Attribute | Purpose |
---|---|
propagation | Defines how the transaction should behave if one already exists (eg, REQUIRED , REQUIRES_NEW ). |
isolation | Sets isolation level (eg, READ_COMMITTED , SERIALIZABLE ). |
rollbackFor | Specify which exceptions trigger rollback (eg, rollbackFor = Exception.class ). |
noRollbackFor | Exceptions that should not trigger rollback. |
readOnly | Optimizes read-only operations (eg, queries). |
Example: Rollback on Checked Exception
By default, Spring only rolls back for unchecked exceptions (subclasses of RuntimeException
). To include checked exceptions:
@Transactional(rollbackFor = Exception.class) public void transferMoney(String from, String to, double amount) throws IOException { // business logic if (amount <= 0) throw new IOException("Invalid amount"); }
Now, IOException
will trigger a rollback.
6. Propagation Behavior: Handling Nested Calls
One of the most misunderstood aspects is transaction propagation .
Common values:
-
REQUIRED
(default): Use existing transaction, or create a new one. -
REQUIRES_NEW
: Always suspend current transaction and start a new one. -
SUPPORTS
: Execute within a transaction if exists, otherwise non-transactional.
Example: Using REQUIRES_NEW
@Service public class PaymentService { @Autowired private AuditService auditService; @Transactional public void processPayment() { // Part of the outer transaction jdbcTemplate.update("INSERT INTO payments..."); // Starts a new transaction; if this fails, outer still can commit auditService.logPayment(); // Continue outer transaction } } @Service public class AuditService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void logPayment() { jdbcTemplate.update("INSERT INTO audit_log..."); // Even if this fails, payment processing may still commit } }
Use REQUIRES_NEW
carefully—especially if you need strong consistency.
7. Common Pitfalls and Best Practices
? Self-Invocation Breaks Proxy
If a method within the same class calls @Transactional
method directly, the transaction is not applied because it bypasses the proxy.
@Service public class SelfCallProblem { public void methodA() { methodB(); // No transaction! Direct call, no proxy } @Transactional public void methodB() { // Not transactional when called from methodA } }
? Fix : Inject the service into itself or reflector logic.
? Best Practices
- Apply
@Transactional
at the service layer , not DAO/repository. - Keep transactions short and focused to reduce lock contention.
- Prefer declarative over programming management.
- Use
readOnly = true
for query methods to improve performance. - Be cautious with
REQUIRES_NEW
—it can lead to partial failures. - Test transactional behavior using
TestTransaction
in integration tests.
8. Programmatic Transaction Management (When You Need More Control)
Sometimes you need fine-grained control. Use TransactionTemplate
:
@Service public class CustomTransactionService { @Autowired private TransactionTemplate transactionTemplate; public void processData() { transactionTemplate.execute(status -> { try { jdbcTemplate.update("INSERT INTO..."); return true; } catch (Exception e) { status.setRollbackOnly(); return false; } }); } }
Useful for conditional logic or when @Transactional
is too rigid.
9. Transaction Management in Spring Boot
Spring Boot auto-configures transaction management if it detects:
- A
DataSource
- Spring Data JPA or similar
Just add:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
Then use @Transactional
freely—no extra setup needed.
Final Thoughts
Spring's transaction management greatly simplifies working with ACID-compliant operations. By using @Transactional
wisely and understanding propagation, isolation, and rollback rules, you can build robust and maintainable applications.
The key is to:
- Use declarative transactions by default.
- Understand how proxies work.
- Avoid long-running transactions.
- Test edge cases involving exceptions and nested calls.
With these practices, you'll avoid common data inconsistencies and build more reliable systems.
Basically, let Spring handle the boilerplate—so you can focus on business logic.
The above is the detailed content of A Guide to Transaction Management in Java and the Spring Framework. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

As an industry leader, Spring+AI provides leading solutions for various industries through its powerful, flexible API and advanced functions. In this topic, we will delve into the application examples of Spring+AI in various fields. Each case will show how Spring+AI meets specific needs, achieves goals, and extends these LESSONSLEARNED to a wider range of applications. I hope this topic can inspire you to understand and utilize the infinite possibilities of Spring+AI more deeply. The Spring framework has a history of more than 20 years in the field of software development, and it has been 10 years since the Spring Boot 1.0 version was released. Now, no one can dispute that Spring

Introduction RESTful APIs have become an integral part of modern WEB applications. They provide a standardized approach to creating and using Web services, thereby improving portability, scalability, and ease of use. In the Java ecosystem, JAX-RS and springmvc are the two most popular frameworks for building RESTful APIs. This article will take an in-depth look at both frameworks, comparing their features, advantages, and disadvantages to help you make an informed decision. JAX-RS: JAX-RSAPI JAX-RS (JavaAPI for RESTful Web Services) is a standard JAX-RSAPI developed by JavaEE for developing REST

Backend learning path: The exploration journey from front-end to back-end As a back-end beginner who transforms from front-end development, you already have the foundation of nodejs,...

I want to modify the requestbody before routing it to the given uri. Modify the body based on the documentation I'm using org.springframework.cloud.gateway.filter.factory.rewrite.modifyrequestbodygatewayfilterfactory. When starting my server, the server fails to start with the following error reason: Element [spring.cloud.gateway.routes[0].filters[0].modifyrequestbody.class] is not bound. \n\nOperation:\

Optimizing program logging: Tips for setting log4j log levels Summary: Program logging plays a key role in troubleshooting, performance tuning, and system monitoring. This article will share tips on setting log4j log levels, including how to set different levels of logs and how to illustrate the setting process through code examples. Introduction: In software development, logging is a very important task. By recording key information during the running process of the program, it can help developers find out the cause of the problem and perform performance optimization and system monitoring.

An in-depth analysis of the architecture and working principles of the Spring framework Introduction: Spring is one of the most popular open source frameworks in the Java ecosystem. It not only provides a powerful set of container management and dependency injection functions, but also provides many other functions, such as transactions. Management, AOP, data access, etc. This article will provide an in-depth analysis of the architecture and working principles of the Spring framework, and explain related concepts through specific code examples. 1. Core concepts of the Spring framework 1.1IoC (Inversion of Control) Core of Spring

Detailed explanation of Oracle database connection methods In application development, database connection is a very important link, which carries the data interaction between the application and the database. Oracle database is a relational database management system with powerful functions and stable performance. In actual development, we need to be proficient in different connection methods to interact with Oracle database. This article will introduce in detail several common connection methods of Oracle database and provide corresponding code examples to help readers better understand and apply

Java reflection mechanism is widely used in Spring framework for the following aspects: Dependency injection: instantiating beans and injecting dependencies through reflection. Type conversion: Convert request parameters to method parameter types. Persistence framework integration: mapping entity classes and database tables. AspectJ support: intercepting method calls and enhancing code behavior. Dynamic Proxy: Create proxy objects to enhance the behavior of the original object.
