Spring Boot |
The @Transactional
annotation in Spring is used to manage transactions declaratively. It simplifies transaction management by allowing developers to define transactional behavior at the method or class level without having to write boilerplate code to begin, commit, or rollback transactions manually.
How @Transactional
Works?
- When a method annotated with
@Transactional
is called, Spring creates a proxy around the method. - The proxy begins a transaction before the method execution and commits it after the method completes successfully.
- If an exception occurs and the transaction is marked as
rollbackFor
, the transaction is rolled back.
Key Features
- Automatic Commit: If no exception occurs, the transaction is committed automatically.
- Automatic Rollback: If a runtime exception occurs, the transaction is rolled back.
- Propagation Management: Allows specifying how transactions should propagate across method calls.
- Isolation Levels: Controls how transactions isolate their operations from other concurrent transactions.
- Read-Only Transactions: Optimizes performance for read-only operations.
Example 1: Basic Usage
Use Case: Updating User Information
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void updateUser(Long userId, String newName) {
User user = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
user.setName(newName);
userRepository.save(user);
// If any exception occurs here, the transaction is rolled back
}
}
Explanation:
- The transaction begins when
updateUser
is called. - If an exception occurs during execution, all changes are rolled back.
Example 2: Rollback for Specific Exceptions
By default, transactions rollback for RuntimeException
. You can customize this behavior:
@Transactional(rollbackFor = Exception.class)
public void performTransaction() throws Exception {
// Some database operations
if (someCondition) {
throw new Exception("Custom exception");
}
}
Here, the transaction will roll back even for checked exceptions.
Example 3: Read-Only Transactions
For read-only operations, you can use @Transactional(readOnly = true)
to optimize performance:
@Transactional(readOnly = true)
public List<User> getAllUsers() {
return userRepository.findAll();
}
How it works:
- Prevents unnecessary locking in the database.
- Indicates to the database driver and JPA provider that no modifications will be made.
Example 4: Propagation Types
@Transactional
allows control over transaction propagation with the propagation
attribute. Common propagation types:
- REQUIRED (Default): Uses the existing transaction or creates a new one if none exists.
- REQUIRES_NEW: Suspends the existing transaction and starts a new one.
- NESTED: Starts a nested transaction within an existing transaction.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(String message) {
logRepository.save(new Log(message));
}
In this example, even if the outer transaction rolls back, this REQUIRES_NEW
transaction will commit.
How Spring Manages Transactions Internally
- Transaction Manager: Spring uses a
PlatformTransactionManager
to manage transactions, such asJpaTransactionManager
for JPA orDataSourceTransactionManager
for JDBC. - Proxy-Based AOP: Spring wraps the transactional method with a proxy to add transactional behavior.
- Thread Binding: Transactions are bound to the current thread using a
TransactionSynchronizationManager
.
Common Pitfalls
-
Calling Transactional Methods Internally: Spring's proxy doesn't work for internal method calls. Always call transactional methods from outside the class.
-
Non-Public Methods:
@Transactional
works only on public methods, as Spring proxies cannot intercept private or protected methods. -
Misconfigured Exceptions: Ensure
rollbackFor
is configured properly to avoid unintentional commits.
Summary
@Transactional
simplifies transaction management in Spring applications.- Supports declarative configuration for commit, rollback, propagation, and isolation.
- Use it effectively by understanding propagation types and performance optimization techniques like read-only transactions.
No comments:
Post a Comment