It runs the method inside a transaction; by default Spring rolls back on unchecked (`RuntimeException`) errors. A common gotcha is self-invocation: calling a `@Transactional` method from the same class bypasses the proxy, so the transaction may not start.
@Service
class PaymentService {
@Transactional
public void pay() {
// DB writes here
}
}In most Spring apps, `@Transactional` is implemented via an AOP **proxy**. The proxy starts a transaction before your method runs and commits/rolls back after it finishes.
Spring rolls back on:
Checked exceptions do **not** trigger rollback unless configured:
@Transactional(rollbackFor = Exception.class)Only calls that go **through the proxy** get transactional behavior. `this.someTransactionalMethod()` stays inside the bean and bypasses the proxy.