Mastering Spring Transaction Management: From Basics to Propagation Types
This article explains the fundamentals of Spring transactions, demonstrates how to set up a Spring Boot project with MySQL and MyBatis, walks through declarative transaction usage, compares REQUIRED, REQUIRES_NEW, and NESTED propagation behaviors with code examples, and highlights common pitfalls and best‑practice steps.
Why Spring Transactions Matter
Transactions guarantee the ACID properties—Atomicity, Consistency, Isolation, Durability—ensuring that a series of database operations either all succeed or all fail. Spring implements transaction management using AOP, allowing developers to focus on business logic while Spring handles commit and rollback.
Background Example
Consider a bank transfer where two operations must happen together: deducting money from the sender and crediting the receiver. Without a transaction, a failure after the first operation would leave the system in an inconsistent state. Spring transactions enforce atomicity for such scenarios.
Quick Start Guide
1. Create two tables tablea and tableb with id and name columns.
CREATE TABLE `tablea` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;
CREATE TABLE `tableb` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;2. Set up a Spring Boot project and add MyBatis and MySQL dependencies:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>3. Implement a controller, service interfaces, mapper, and entity classes (code snippets omitted for brevity). Configure the datasource in application.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
type-aliases-package: tech.shuyi.javacodechip.spring_transaction.model
configuration:
map-underscore-to-camel-case: trueRunning the application and accessing /api/spring-transaction inserts a row into both tables when the transaction succeeds.
Declarative Transaction Usage
Apply @Transactional on service methods to enable transaction management. Example:
@Transactional
public void methodA(){
tableService.insertTableA(new TableEntity());
transactionServiceB.methodB();
}If methodB throws a RuntimeException, the whole transaction rolls back.
Propagation Types
REQUIRED (default)
If a transaction already exists, the called method joins it; otherwise a new transaction is created. Any exception in either method causes a rollback of the whole transaction.
public void methodA(){
tableService.insertTableA(new TableEntity());
transactionServiceB.methodB(); // methodB annotated with @Transactional
}
@Transactional
public void methodB(){
tableService.insertTableB(new TableEntity());
throw new RuntimeException();
}Result: tablea is inserted, tableb is not.
REQUIRES_NEW
The called method always starts a new, independent transaction. The outer transaction will roll back only if it does not catch the inner exception.
@Transactional
public void methodA(){
tableService.insertTableA(new TableEntity());
transactionServiceB.methodB(); // REQUIRES_NEW
throw new RuntimeException();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB(){
tableService.insertTableB(new TableEntity());
}Result: tablea rolls back, tableb remains.
NESTED
The called method runs in a nested transaction. If the outer transaction rolls back, the nested one rolls back as well. If the nested transaction rolls back, the outer transaction rolls back only when the exception propagates (i.e., is not caught).
@Transactional
public void methodA(){
tableService.insertTableA(new TableEntity());
try {
transactionServiceB.methodB(); // NESTED
} catch (Exception e) {
// exception handled, outer transaction continues
}
}
@Transactional(propagation = Propagation.NESTED)
public void methodB(){
tableService.insertTableB(new TableEntity());
throw new RuntimeException();
}Result: tablea is inserted, tableb is not.
Choosing the Right Propagation
Analyze the business requirement to decide whether child operations should share the same transaction or be independent.
Annotate service methods with @Transactional and set the appropriate propagation attribute.
Common Transaction Pitfalls
Calling a @Transactional method from another method in the same class bypasses the proxy, causing the transaction to be ignored.
Only public methods are eligible for Spring’s transaction interception.
The class must be managed by Spring (e.g., annotated with @Service or declared as a bean).
The underlying database must support transactions.
Special Note
Spring rolls back only on unchecked exceptions ( RuntimeException) and Error. Throwing a checked Exception does not trigger a rollback unless configured otherwise.
@Transactional
public void methodA() throws Exception {
tableService.insertTableA(new TableEntity());
transactionServiceB.methodB();
}
@Transactional
public void methodB() throws Exception {
tableService.insertTableB(new TableEntity());
throw new Exception(); // No rollback
}References
SegmentFault – “从头到尾说一次 Spring 事务管理(器)”
知乎 – “Spring 事务原理一探”
JavaGuide – “Spring 事务详解”
博客园 – “事务之六:spring 嵌套事务”
云扬四海 – “Transaction rolled back because it has been marked as rollback-only”
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
