Transaction
Multiple actions performed as a single group
ACID Transactions
AI-generated
- Atomicity: a transaction commits as one unit or has no effect.
- Consistency: a committed transaction preserves declared invariants such as constraints; the application still has to encode the correct business rules.
- Isolation: concurrent transactions interact according to the configured isolation level. Weaker levels allow specific anomalies.
- Durability: an acknowledged commit survives the failures covered by the database's persistence and replication configuration.
Transaction Types
AI-generated
- Local: one transactional resource, such as a JDBC connection.
- Global/distributed: one unit of work coordinates multiple transactional resources, commonly through JTA/XA. This adds failure modes and should not be confused with an ordinary transaction inside one database.
Spring Framework
Consistent programming model across global and local transactions.
Spring Transaction management types
Programmatic
- Custom code for transaction management.
Example:
public void saveTicket(Ticket ticket) {
Session session = sessionFactory.getCurrentSession();
session.getTransaction().begin(); //--
session.save(ticket); // | <=== transaction
session.getTransaction().commit(); //--
}
Declarative
- Manages transaction using Spring-specific annotations.
- Separates transaction management from business code.
Example:
@Transactional
public void scheduleRelease(Ticket ticket, Release release) {
ticketDao.saveTicket(ticket);
assignToRelease(ticket, release);
doOtherStuff(ticket);
}
Manages everything:
- Begin
- Suspend
- Commit
- Rollback
- Transactional parameters
Transaction Managers
Programmatic Transaction Management:
- Transaction template: Similar to Spring templates like
JdbcTemplateand other available templates. - Platform transaction manager: Handles transactions across Hibernate, JDBC, JPA, JMS, etc.
Spring Transaction Managers:
- Platform transaction manager
- JTA
- Hibernate
- DataSource
- JPA
@Transactional annotation
- Proxy is created to hold transaction management code.
- Annotation used at the class, interface or method level.
- Transaction propagation is handled automatically.
NOTE: In Spring boot, it works without configuration.
Spring Configuration
- JPA Transaction Manager: Registers a transaction manager for us.
- Additional configuration: Datasource, entity manager, repositories.
- Spring Data Repositories.
Lifecycle and Scope
Database Transaction
@Transactional defines a single transaction, in the scope of a persistence context.
Persistence Context
- Defined in JPA
- Handles a set of entities that contain data to be persisted.
How @Transactional works?
Via proxies!
Transactional call path
AI-generated
Proxy
- Transaction Interceptor: Intercepts method calls.
- Platform transaction manager: Handles transactions.
Difference proxies in Spring (JPA?) transaction handling:
- Persistence context proxy
- Entity manager proxy
- Transaction aspect
- Transaction manager
Rollbacks
AI-generated
By default, Spring marks a transaction for rollback when an unchecked
RuntimeException or an Error escapes the transactional boundary. Checked
exceptions do not trigger rollback unless configured.
- Use
@Transactional(rollbackFor=Exception.class)to state otherwise. - Use
@Transactional(noRollbackFor=SpecificException.class)to avoid rollback on a specific exception.
The usual proxy-based flow is:
- Application code throws out of the proxied transactional method.
- The transaction interceptor applies rollback rules.
- The transaction manager commits or rolls back the resource transaction.
Self-invocation normally bypasses the proxy, and catching an exception inside the method prevents the interceptor from seeing it unless the transaction is marked rollback-only explicitly.
NOTE:
To enable the transaction logging from Spring, set: logging.level.org.springframework.transaction.interceptor=TRACE
Transaction management code
Configuration:
private final TransactionTemplate transactionTemplate;
// constructor
public ReleaseService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
this.transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRES_NEW");
this.transactionTemplate.setReadOnly(true);
}
A simple 2 step transaction with the above configuration:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
try {
} catch (NoSuchElementException exception) {
exception.printStackTrace();
status.setRollbackOnly();
}
}
});
Fine-grained control in programmatic transaction management, using platform transaction manager directly.
public Release scheduleRelease(Release release) {
TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
try {
createTickets(release);
assignTicketsToRelease(release.getId(), release.getTickets());
transactionManager.commit(transactionStatus);
} catch (RuntimeException e) {
transactionManager.rollback(transactionStatus);
throw e;
}
return release;
}
Declarative transaction management (vs Programmatic)
- Manage transaction via configuration.
- Separate transaction logic from business logic.
- Easy to maintain.
- Preferred when a lot of transaction logic.