Spring Data JPA - transactions
Reading material
- https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
- https://spring.io/guides/gs/managing-transactions/
- https://www.baeldung.com/transaction-configuration-with-jpa-and-spring
@EnableTransactionManagement in Spring Boot
- https://stackoverflow.com/questions/40724100/enabletransactionmanagement-in-spring-boot
- https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html
- https://www.geeksforgeeks.org/spring-boot-transaction-management-using-transactional-annotation/
ACID
The acronym for the four properties guaranteed by transactions: atomicity, consistency, isolation, and durability.
How to implement transactions using Spring JPA?
Basically, there are two distinct ways to configure Transactions, each with its own advantages.
- annotations
- AOP
Configure Transactions
@EnableTransactionManagement
If we’re using a Spring Boot project and have a
spring-data-*
orspring-tx
dependencies on the classpath, then transaction management will be enabled by default.
If not, we can enable it using @EnableTransactionManagement
annotation
Spring 3.1 introduces the @EnableTransactionManagement annotation that we can use in a @Configuration class to enable transactional support:
@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{
...
@Transactional
The @Transactional
Annotation
With transactions configured, we can now annotate a bean with @Transactional
either at the class or method level:
@Service
@Transactional
public class FooService {
//...
}
The annotation supports further configuration as well:
- the Propagation Type of the transaction
- the Isolation Level of the transaction
- a Timeout for the operation wrapped by the transaction
- a readOnly flag – a hint for the persistence provider that the transaction should be read only
- the Rollback rules for the transaction
Note that by default, rollback happens for runtime, unchecked exceptions only. The checked exception does not trigger a rollback of the transaction. We can, of course, configure this behavior with the rollbackFor and noRollbackFor annotation parameters.
Potential Pitfalls
Transactions and Proxies
At a high level, Spring creates proxies for all the classes annotated with @Transactional
, either on the class or on any of the methods. The proxy allows the framework to inject transactional logic before and after the running method, mainly for starting and committing the transaction.
What’s important to keep in mind is that, if the transactional bean is implementing an interface, by default the proxy will be a Java Dynamic Proxy. This means that only external method calls that come in through the proxy will be intercepted. Any self-invocation calls will not start any transaction, even if the method has the @Transactional
annotation.
Another caveat of using proxies is that only public methods should be annotated with @Transactional
. Methods of any other visibilities will simply ignore the annotation silently as these are not proxied.