@Transactional
is an annotation in Spring Framework that provides declarative transaction management. It is used to define the transactional behavior of a method or class, ensuring that database operations within the annotated scope are executed as part of a single transaction.
Key Features of @Transactional
- Atomicity: Ensures that all operations within a transaction are treated as a single unit of workâeither all succeed or all fail.
- Declarative Transaction Management: No need to write boilerplate code for managing transactions; Spring handles it automatically.
- Rollback: Automatically rolls back the transaction if an exception occurs during execution.
- Integration with Persistence Frameworks: Works seamlessly with JPA, Hibernate, JDBC, and other persistence frameworks.
Common Usage
-
On Methods:
When applied to a method, the transaction begins when the method starts and commits or rolls back when the method finishes.123456@Transactionalpublic void performDatabaseOperations() {// All operations here are part of the same transactionrepository.save(entity1);repository.save(entity2);} -
On Classes:
When applied to a class, all methods in the class inherit the transactional behavior.12345678910@Transactionalpublic class MyService {public void method1() {// Transactional}public void method2() {// Transactional}}
How Does It Work?
Spring wraps the annotated method in a proxy. The proxy intercepts method calls and:
- Begins a transaction before the method execution.
- Commits the transaction if the method completes successfully.
- Rolls back the transaction if an exception occurs.
Key Attributes of @Transactional
-
propagation
: Defines how the transaction is propagated across method calls.REQUIRED
(default): Uses the existing transaction or creates a new one if none exists.REQUIRES_NEW
: Suspends the current transaction and creates a new one.NESTED
: Creates a nested transaction.
1234@Transactional(propagation = Propagation.REQUIRES_NEW)public void someMethod() {// Always starts a new transaction} -
isolation
: Sets the isolation level for the transaction, controlling how changes in one transaction are visible to others.READ_UNCOMMITTED
,READ_COMMITTED
(default),REPEATABLE_READ
,SERIALIZABLE
.
1234@Transactional(isolation = Isolation.REPEATABLE_READ)public void isolatedMethod() {// Transaction with repeatable read isolation} -
readOnly
: Optimizes transactions that perform only read operations (e.g., skips locking in some databases).1234@Transactional(readOnly = true)public List<Entity> fetchData() {return repository.findAll();} -
timeout
: Sets the maximum duration for a transaction in seconds. If exceeded, the transaction is rolled back.1234@Transactional(timeout = 10)public void performLongOperation() {// Rolls back if it takes longer than 10 seconds} -
rollbackFor
andnoRollbackFor
: Specify exceptions that should or should not trigger a rollback.1234@Transactional(rollbackFor = CustomException.class)public void someOperation() {// Rolls back on CustomException}
Example: Using @Transactional
in a Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@Service public class UserService { @Autowired private UserRepository userRepository; @Transactional public void createUser(String name, String email) { User user = new User(); user.setName(name); user.setEmail(email); userRepository.save(user); // Simulate an exception if (email == null) { throw new IllegalArgumentException("Email cannot be null"); } } } |
- If
email
isnull
, the exception triggers a rollback, and the user is not saved to the database.
Rollback Behavior
By default:
- Checked Exceptions: Do not trigger a rollback.
- Runtime Exceptions (unchecked): Trigger a rollback.
You can customize this behavior using rollbackFor
and noRollbackFor
.
Summary
@Transactional
in Spring Boot simplifies transaction management by:
- Automatically handling transaction start, commit, and rollback.
- Supporting custom configurations like propagation, isolation, and timeouts.
- Integrating seamlessly with Spring Data, JPA, and Hibernate.
This declarative approach eliminates boilerplate code and ensures consistency and data integrity in database operations.