Spring’s transaction abstraction lets you demarcate units of work so that either every participating database statement succeeds or the entire sequence is rolled back. While JDBC already offers Connection#setAutoCommit(false), Spring adds portable configuration, propagation rules, and AOP-based declarations that can be applied at the service layer instead of polluting your data-access code.
Core API
public interface TransactionManager {
void commit(TransactionStatus tx) throws TransactionException;
void rollback(TransactionStatus tx) throws TransactionException;
}
The concrete implementation most often used with MyBatis or plain JDBC is DataSourceTransactionManager. It delegates to java.sql.Connection under the hood, so no extra libraries are required.
Enabling Annotation-Driven Transactions
-
Annotate the service interface (preferred) or the concrete class with
@Transactional. Placinng it on the enterface keeps your implementation decoupled from Spring APIs.public interface PaymentService { @Transactional void transfer(String from, String to, BigDecimal amount); } -
Expose a transaction manager bean. The following Java-config example wires the application’s
DataSourceintoDataSourceTransactionManager.@Bean public PlatformTransactionManager txManager(DataSource ds) { return new DataSourceTransactionManager(ds); } -
Activate processing of
@Transactionalby adding@EnableTransactionManagementto any@Configurationclass.@Configuration @ComponentScan("com.example") @Import({DataConfig.class, MyBatisConfig.class}) @EnableTransactionManagement public class AppConfig { }
Transaction Participants
- Transaction Manager – the method that starts the logical unit of work (usually a service method annotated with
@Transactional). - Participant Resource – any repository or DAO method invoked inside that unit. By default it simply joins the existing transaction instead of creating a new one.
Propagation Rules
Propagation defines how a participant reacts when it is invoked inside an already running transaction. The most common settings are:
| Propagation | Behaviour |
|---|---|
REQUIRED |
Join the current transaction; create a new one if none exists (default). |
REQUIRES_NEW |
Suspend the current transaction and start a brand-new one. |
public interface AuditService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
void logTransfer(String from, String to, BigDecimal amount);
}
Using REQUIRES_NEW above guarantees that the audit record is committed even if the surrounding business transaction rolls back.