Backend Development 13 min read

Understanding Spring Transaction Fundamentals and Propagation Mechanisms

This article explains the core principles of Spring transactions, how they rely on database support, demonstrates JDBC transaction steps, introduces Spring's declarative transaction management, compares JDK and CGLIB proxies, and details propagation attributes, isolation levels, and read‑only transaction usage with practical code examples.

Top Architect
Top Architect
Top Architect
Understanding Spring Transaction Fundamentals and Propagation Mechanisms

Spring Transaction Basic Principles

Spring transactions fundamentally depend on the underlying database's transaction support; without it, Spring cannot provide transaction functionality. For pure JDBC operations, the typical steps are obtaining a connection, disabling auto‑commit, performing CRUD, committing or rolling back, and finally closing the connection.

Get connection: Connection con = DriverManager.getConnection();

Begin transaction: con.setAutoCommit(false);

Execute CRUD operations

Commit or rollback: con.commit(); / con.rollback();

Close connection: con.close();

When using Spring's transaction management, steps 2 and 4 are handled automatically.

Spring Transaction Mechanism

Spring provides a unified transaction mechanism across various data‑access technologies via the PlatformTransactionManager interface, with specific implementations for each technology.

Example of defining a transaction manager bean:

@Bean
public PlatformTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setDataSource(dataSource());
    return transactionManager;
}

Declarative Transaction

Spring supports declarative transactions using the @Transactional annotation on classes or methods, which is processed by AOP proxies.

@Transactional
public void saveSomething(Long id, String name) {
    // database operations
}

Note: The annotation comes from org.springframework.transaction.annotation , not javax.transaction .

AOP Proxy Implementations

JDK dynamic proxy works on interfaces; private methods are not intercepted.

CGLIB creates subclasses; private methods are also not intercepted.

Java Dynamic Proxy Steps

Implement InvocationHandler to define custom handling.

Use Proxy with a class loader and interfaces to create the proxy class.

Obtain the proxy class constructor via reflection.

Instantiate the proxy, passing the handler instance.

CGLIB Proxy

CGLIB (Code Generation Library) generates subclasses at runtime using ASM, allowing proxying of classes without interfaces, and is commonly used for Spring AOP.

Spring Transaction Propagation Attributes

Propagation defines how Spring handles multiple concurrent transactions:

PROPAGATION_REQUIRED (default): joins an existing transaction or creates a new one if none exists.

PROPAGATION_REQUIRES_NEW : suspends the current transaction and starts a new one.

PROPAGATION_SUPPORTS : joins an existing transaction if present; otherwise executes without a transaction.

PROPAGATION_NESTED : creates a nested transaction using a savepoint, allowing independent rollback within the outer transaction.

Example of handling a nested transaction with savepoint:

void methodA() {
    try {
        ServiceB.methodB();
    } catch (SomeException) {
        // other business logic
    }
}

Database Isolation Levels

Isolation levels control phenomena such as dirty reads, non‑repeatable reads, and phantom reads. Higher isolation improves data integrity but reduces concurrency.

Common levels:

Read Committed (default for many databases like SQL Server, Oracle)

Repeatable Read (default for MySQL InnoDB)

Spring Isolation Levels

Spring maps its isolation constants to the underlying database levels; developers can specify them via the @Transactional(isolation = Isolation.X) attribute.

Nested Transactions

Using PROPAGATION_NESTED , an inner transaction can roll back to a savepoint without affecting the outer transaction, enabling complex business scenarios where partial failures should not corrupt overall data.

Read‑Only Transactions

Annotating a method with @Transactional(readOnly = true) signals the datasource that the transaction will not modify data, allowing potential performance optimizations. The default isolation and propagation (DEFAULT and REQUIRED) still apply.

Spring Boot Transaction Support

Spring Boot automatically enables annotation‑driven transaction management via org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration .

Recommendations

For critical transactional code, prefer using Spring's TransactionCallback API for fine‑grained control. If using annotations, ensure a solid understanding of propagation and isolation to avoid unexpected behavior.

BackendJavatransactionSpringisolationPropagationDeclarative
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.