I just started working on a Spring-data, Hibernate, MySQL, JPA project. I switched to spring-data so that I wouldn't have to worry about creating queries by hand.
I noticed that the use of @Transactional
isn't required when you're using spring-data since I also tried my queries without the annotation.
Is there a specific reason why I should/shouldn't be using the @Transactional
annotation?
Works:
@Transactional public List listStudentsBySchool(long id) { return repository.findByClasses_School_Id(id); }
Also works:
public List listStudentsBySchool(long id) { return repository.findByClasses_School_Id(id); }
Thanks in advance!
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.
The annotation @EnableTransactionManagement tells Spring that classes with the @Transactional annotation should be wrapped with the Transactional Aspect. With this the @Transactional is now ready to be used.
The @Transactional annotation is metadata that specifies that an interface, class, or method must have transactional semantics; for example, "start a brand new read-only transaction when this method is invoked, suspending any existing transaction".
You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies.
What is your question actually about? The usage of the @Repository
annotation or @Transactional
.
@Repository
is not needed at all as the interface you declare will be backed by a proxy the Spring Data infrastructure creates and activates exception translation for anyway. So using this annotation on a Spring Data repository interface does not have any effect at all.
@Transactional
- for the JPA module we have this annotation on the implementation class backing the proxy (SimpleJpaRepository
). This is for two reasons: first, persisting and deleting objects requires a transaction in JPA. Thus we need to make sure a transaction is running, which we do by having the method annotated with @Transactional
.
Reading methods like findAll()
and findOne(…)
are using @Transactional(readOnly = true)
which is not strictly necessary but triggers a few optimizations in the transaction infrastructure (setting the FlushMode
to MANUAL
to let persistence providers potentially skip dirty checks when closing the EntityManager
). Beyond that the flag is set on the JDBC Connection as well which causes further optimizations on that level.
Depending on what database you use it can omit table locks or even reject write operations you might trigger accidentally. Thus we recommend using @Transactional(readOnly = true)
for query methods as well which you can easily achieve adding that annotation to you repository interface. Make sure you add a plain @Transactional
to the manipulating methods you might have declared or re-decorated in that interface.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With