When building enterprise-level applications with Spring Boot, transaction management is critical to ensure data integrity. Spring provides robust support for declarative transactions using the @Transactional
annotation. One of the most powerful aspects of this annotation is the propagation behavior.
In this post, we'll cover:
- What is transaction propagation?
- Different propagation types in Spring
- Real-world use cases for each type
- Code examples
π What is Transaction Propagation?
Transaction propagation determines how Spring should handle transaction boundaries when a method annotated with @Transactional
is called within the context of another transaction.
In simpler terms:
"If method A is already running in a transaction, and it calls method B (which is also transactional), what should happen to method B?"
π§ Propagation Types
Spring defines the following propagation behaviors in the Propagation
enum:
Propagation Type | Description |
---|---|
REQUIRED |
Join current transaction or create a new one if none exists |
REQUIRES_NEW |
Always start a new transaction, suspending the existing one |
NESTED |
Execute within a nested transaction if a current one exists |
SUPPORTS |
Join the current transaction if available; else run non-transactionally |
NOT_SUPPORTED |
Always run non-transactionally, suspending any existing transaction |
NEVER |
Must run non-transactionally; throws exception if transaction exists |
MANDATORY |
Must join an existing transaction; throws exception if none exists |
β Common Use Cases with Examples
1. REQUIRED (default)
@Transactional(propagation = Propagation.REQUIRED)
public void processOrder() {
saveOrder();
updateInventory();
}
π§ Use case: Most common. Use when all method calls should participate in the same transaction β either all succeed or all fail.
2. REQUIRES_NEW
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logAuditTrail() {
// Save audit log even if outer transaction fails
}
π§ Use case:
Useful when you want to persist certain changes regardless of the outcome of the parent transaction.
π Real-world example: Logging audit events, sending emails, or payment retries that should not roll back with business failure.
3. NESTED
@Transactional(propagation = Propagation.NESTED)
public void applyDiscount() {
// Rollback this logic only, not the parent transaction
}
π§ Use case:
Allows partial rollbacks within the main transaction using savepoints.
β οΈ Note: Your database must support savepoints (e.g., H2, PostgreSQL, Oracle). MySQL with MyISAM doesn't.
4. SUPPORTS
@Transactional(propagation = Propagation.SUPPORTS)
public List<Product> getAllProducts() {
return productRepository.findAll();
}
π§ Use case:
Use when the method can work with or without a transaction (read-only operations).
5. NOT_SUPPORTED
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void sendEmailNotification() {
// Should not participate in any transaction
}
π§ Use case:
Non-transactional operations (e.g., external API calls) that shouldnβt be part of the transaction to avoid rollback delays.
6. NEVER
@Transactional(propagation = Propagation.NEVER)
public void loadStaticData() {
// Throws exception if a transaction exists
}
π§ Use case:
For methods that must not be called within a transaction, such as logging frameworks or async tasks.
7. MANDATORY
@Transactional(propagation = Propagation.MANDATORY)
public void updateUserPoints() {
// Only works if called from within a transaction
}
π§ Use case:
To enforce that certain methods must be part of an active transaction β useful for modular business services.
β οΈ Common Pitfalls
- Calling transactional methods within the same class: Spring proxies won't apply the transaction.
- π‘ Fix: Move the transactional method to a different class or use
AopContext
.
Confusing
REQUIRES_NEW
andNESTED
: They behave differently under rollback scenarios.REQUIRES_NEW misuse: Overuse can cause performance issues due to excessive transaction overhead.
π Conclusion
Spring's transaction propagation gives you fine-grained control over how transactions behave across service layers. Choosing the right propagation type depends on the business requirements, rollback strategies, and data integrity constraints.
π Quick Reference
Propagation | Joins Existing Txn? | Creates New Txn? | Throws if None Exists |
---|---|---|---|
REQUIRED | β | β (if none) | β |
REQUIRES_NEW | β (suspends) | β | β |
NESTED | β (nested savepoint) | β (if none) | β |
SUPPORTS | β | β | β |
NOT_SUPPORTED | β (suspends) | β | β |
NEVER | β | β | β |
MANDATORY | β | β | β |
Top comments (1)
I recently made a Commercial grade Project using Spring Boot. Would love your feedback or suggestions on how I can expand and improve it, check out here
linkedin.com/feed/update/urn:li:ac...