@Transactional
@Transactional
When You Use @Transactional at the Class Level:
All public methods of the class are automatically transactional, as if you had added @Transactional on each method.
Public method ==> Runs within a transaction
Private / protected method ==> Not transactional (no proxy interception)
Internal method call ==> Not transactional (e.g., calling one method from another within same class)
Spring AOP-based proxy ==> Only public methods are proxied and eligible for transaction management
With Proxy (via @Transactional): Spring creates this proxy automatically when you use @Transactional.
userService.updateUser();
Goes through proxy first:
1. Start Transaction
2. Call real method
3. Commit or Rollback Transaction
Without Proxy (without @Transactional):
userService.updateUser();
Directly runs the real updateUser() method
Case 1: methodA() and methodB() are in the same class
@Service
public class UserService {
@Transactional
public void methodA() {
// DB queries
methodB(); // self-invocation
// DB queries
}
@Transactional
public void methodB() {
// DB queries
}
}
TransactionA is opened when methodA() is called.
All DB queries inside methodA() are executed inside TransactionA.
methodB() is called directly, NOT via proxy, so its @Transactional is ignored.
Therefore, methodB() also runs inside TransactionA.
The entire thing — methodA() and methodB() — commit or roll back together.
Case 2: methodB() is in another class (ServiceB)
@Service
public class ServiceB {
@Transactional
public void methodB() {
// DB queries
}
}
@Service
public class UserService {
@Autowired
private ServiceB serviceB;
@Transactional
public void methodA() {
// DB queries
serviceB.methodB(); // cross-bean call
// DB queries
}
}
methodA() starts TransactionA.
All queries before serviceB.methodB() are part of TransactionA.
Now it depends on transaction propagation:
If methodB() has @Transactional(propagation = Propagation.REQUIRED) (default):
It joins TransactionA, doesn't create a new one.
So methodB() runs in the same transaction as methodA.
Both can be rolled back together.
If methodB() has @Transactional(propagation = Propagation.REQUIRES_NEW):
@Service
public class ServiceB {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// DB queries
}
}
A new transaction (TransactionB) is started.
Now methodB runs in a separate transaction.
It commits or rolls back independently of methodA.
- The DB loads the row from disk into its own memory (RAM) — this is DB server RAM, not your app.
- Any updates or deletes are held in a transaction log (Write-Ahead Log) inside the DB.
- These changes are not visible to other transactions (unless isolation level allows).
- The DB only applies the changes to disk (permanently) when you commit the transaction.
Comments
Post a Comment