Backend Development 31 min read

Spring Transaction Management: Concepts, Configuration, and Best Practices

This article explains the fundamentals of database transactions, the ACID properties, and how Spring provides both declarative and programmatic transaction support through three core interfaces, detailed configuration examples in XML and Java, and a deep dive into transaction attributes such as isolation, propagation, rollback rules, read‑only mode, and timeout.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Spring Transaction Management: Concepts, Configuration, and Best Practices

1. What Is a Transaction

A database transaction is a logical unit of work that must either complete entirely or have no effect at all, ensuring atomicity, consistency, isolation, and durability (ACID).

Typical use case: a money transfer where two updates must succeed or fail together.

2. Transactions in Spring

2.1 Two Usage Styles

Spring supports declarative (via AOP) and programmatic transactions. Declarative is preferred for low coupling; programmatic embeds transaction code directly in business logic.

2.2 Three Core Infrastructure Interfaces

PlatformTransactionManager

TransactionDefinition

TransactionStatus

These interfaces abstract transaction operations across different data sources.

2.2.1 PlatformTransactionManager

Key methods:

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(@Nullable TransactionDefinition definition);
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;
}

Implementations include DataSourceTransactionManager , HibernateTransactionManager , and JpaTransactionManager .

2.2.2 TransactionDefinition

Describes transaction attributes (isolation, propagation, timeout, read‑only, rollback rules). Example methods:

int getIsolationLevel();
String getName();
int getPropagationBehavior();
int getTimeout();
bool isReadOnly();

Implementations such as DefaultTransactionDefinition are used to configure programmatic transactions.

2.2.3 TransactionStatus

Represents the current transaction state. Important methods:

boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();

3. Programmatic Transactions

Using PlatformTransactionManager :

@Service
public class TransferService {
    @Autowired JdbcTemplate jdbcTemplate;
    @Autowired PlatformTransactionManager txManager;
    public void transfer() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = txManager.getTransaction(def);
        try {
            jdbcTemplate.update("update user set account=account+100 where username='zhangsan'");
            int i = 1/0; // simulate error
            jdbcTemplate.update("update user set account=account-100 where username='lisi'");
            txManager.commit(status);
        } catch (DataAccessException e) {
            txManager.rollback(status);
        }
    }
}

Using TransactionTemplate :

@Service
public class TransferService {
    @Autowired JdbcTemplate jdbcTemplate;
    @Autowired TransactionTemplate txTemplate;
    public void transfer() {
        txTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    jdbcTemplate.update("update user set account=account+100 where username='zhangsan'");
                    int i = 1/0;
                    jdbcTemplate.update("update user set account=account-100 where username='lisi'");
                } catch (DataAccessException e) {
                    status.setRollbackOnly();
                }
            }
        });
    }
}

4. Declarative Transactions

Declarative configuration can be done via XML, Java, or a mix of both.

4.1 XML Configuration

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql:///spring_tran?serverTimezone=Asia/Shanghai"/>
    <property name="username" value="root"/>
    <property name="password" value="123"/>
</bean>

<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="add*"/>
        <tx:method name="insert*" isolation="SERIALIZABLE"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="pc1" expression="execution(* com.example.service.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pc1"/>
</aop:config>

4.2 Java Configuration

@Configuration
@EnableTransactionManagement
public class JavaConfig {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUrl("jdbc:mysql:///test01?serverTimezone=Asia/Shanghai");
        ds.setUsername("root");
        ds.setPassword("123");
        return ds;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource ds) { return new JdbcTemplate(ds); }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

@Service
public class UserService {
    @Transactional
    public void update() { /* business logic */ }
}

4.3 Mixed Configuration

Combine XML and Java by importing XML with @ImportResource and defining beans in Java.

5. Transaction Attributes

5.1 Isolation Level

Spring supports MySQL isolation levels (READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE). Default follows the database setting.

Programmatic example:

transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);

Declarative example:

@Transactional(isolation = Isolation.SERIALIZABLE)
public void update() { /* ... */ }

5.2 Propagation Behavior

Spring defines seven propagation types (REQUIRED, SUPPORTS, MANDATORY, REQUIRES_NEW, NOT_SUPPORTED, NEVER, NESTED). Example enum snippet:

public enum Propagation {
    REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
    SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
    MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
    REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
    NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
    NEVER(TransactionDefinition.PROPAGATION_NEVER),
    NESTED(TransactionDefinition.PROPAGATION_NESTED);
    private final int value;
    Propagation(int value) { this.value = value; }
    public int value() { return this.value; }
}

Declarative configuration example:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void update() { /* ... */ }

5.3 Rollback Rules

By default, only unchecked exceptions trigger rollback. Use rollbackFor to include checked exceptions or noRollbackFor to exclude specific unchecked ones.

@Transactional(rollbackFor = IOException.class)
public void handle() { /* ... */ }

@TransactionAdvice ... rollback-for="java.io.IOException" ...

5.4 Read‑Only

Mark read‑only transactions for methods that only perform queries to avoid unnecessary write locks.

@Transactional(readOnly = true)
public List
findAll() { return jdbcTemplate.query(...); }

5.5 Timeout

Specify the maximum execution time (seconds) after which the transaction is rolled back.

@Transactional(timeout = 10)
public void longRunningTask() { /* ... */ }

6. Common Pitfalls

Transactions only apply to public methods.

Self‑invocation bypasses Spring proxies, so internal method calls with @Transactional will not start a transaction.

Prefer placing @Transactional on implementation classes rather than interfaces unless using interface‑based proxies.

7. Summary

Spring provides a comprehensive transaction framework that abstracts the underlying resource, offers flexible configuration, and supports fine‑grained control over isolation, propagation, rollback, read‑only mode, and timeout, enabling developers to write reliable and maintainable data‑access code.

backendJavatransactionSpringDeclarativeProgrammatic
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

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.