What is the usage of @Transactional in Java?
@Transactional is an annotation in Java that is used to indicate that a method should be executed within a transaction. It can be applied at the class level or method level.
When @Transactional annotation is used at the class level, transactions will be applied to all methods within the class. This implies that each method in the class will be wrapped within a transaction, and when one method calls another method, they will be executed within the same transaction.
When using the @Transactional annotation at the method level, only the annotated method will be executed within a transaction. This allows you to selectively wrap certain methods in a transaction, while others will not be.
The @Transactional annotation can have various attributes to define the behavior of the transaction, such as propagation, isolation level, timeout, and so on. Some common attributes include:
- Propagation refers to the definition of how transactions are spread within a method call chain, indicating how transactions are handled. For example, REQUIRES_NEW signifies that a new transaction is created with each call.
- Isolation: This defines the level of isolation of a transaction, determining how transactions are handled in a concurrent environment. Common isolation levels include READ_COMMITTED and SERIALIZABLE.
- Timeout: determines the maximum amount of time a transaction can go without being submitted before it automatically rolls back.
- readOnly: Indicates whether the transaction is read-only. If the transaction only involves read operations, it can be set to true to improve performance.
Here is an example using the @Transactional annotation:
@Service
@Transactional
public class ProductService {
@Autowired
private ProductRepository productRepository;
public void createProduct(Product product) {
productRepository.save(product);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateProduct(Product product) {
productRepository.save(product);
}
@Transactional(readOnly = true)
public Product getProductById(Long id) {
return productRepository.findById(id).orElse(null);
}
}
In the example above, the createProduct and getProductById methods will be executed within the same transaction. The updateProduct method will be executed in a new transaction, even if it is called by the createProduct method.