Transactions with @Transactional
Commit several writes as one unit, and learn which exceptions actually roll back.
Open this lesson in the learning hubKey points
- Put
@Transactionalon the service method so several repository calls commit or fail together. - Only
RuntimeExceptionandErrorroll back. A checked exception commits unless you addrollbackFor. - Catching the exception inside the method hides it from the proxy, and the transaction then commits happily.
readOnly = truelets Hibernate skip dirty checking and lets the driver route to a replica.- Default propagation
REQUIREDjoins the caller transaction;REQUIRES_NEWsuspends it and opens another. - Keep transactions short. Never make a remote HTTP call while a database connection is held open.
Example
@Service
public class CheckoutService {
@Transactional // one unit: both writes, or neither
public Order checkout(long cartId) {
Cart cart = carts.findById(cartId).orElseThrow(CartNotFoundException::new);
stock.reserve(cart.items()); // UPDATE stock
Order order = orders.save(Order.from(cart)); // INSERT order
return order; // the commit happens at this boundary
}
@Transactional(rollbackFor = ExportFailedException.class) // checked: opt in
public void exportDaily() throws ExportFailedException {
/* ... */
}
@Transactional(readOnly = true) // no dirty checking, no flush
public List<Order> history(String email) {
return orders.findByCustomerEmail(email);
}
@Transactional
public void swallowed(long id) {
try {
risky(id);
} catch (RuntimeException ex) {
log.warn("ignored", ex); // the proxy never sees it, so this COMMITS
}
}
}
The transaction ends at the boundary of the annotated method - and only an unchecked exception rolls it back.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.