Jul 26, 2015
The magic of @Transactional and its performance
I was planning to write a small article about the rollbackFor
parameter for @Trnsactional annotation. But when I
was preparing the code examples, I decided to do some benchmarks. Let’s start with the brief annotation description.
@Transactional
@Transactinal is annotation which allows you to work with databases’ transactions in the declarative way.
This is pretty convenient - you don’t need to think about direct transactions management and exceptions handling. Everything will be done automatically in the proxy class. This image (from spring documentation) show how class hierarchy looks like:
So, it looks pretty clear. JavaDoc about this annotation is always there and gives enough information to get started. But there’s one unclear thing with exception handling - here’s an example:
Will it be commited? - Yes, it will!
The documentation says:
Although EJB container default behavior automatically rolls back the transaction on a system exception (usually a runtime exception), EJB CMT does not roll back the transaction automatically on anapplication exception (that is, a checked exception other than java.rmi.RemoteException). While the Spring default behavior for declarative transaction management follows EJB convention (roll back is automatic only on unchecked exceptions), it is often useful to customize this behavior.
Okaaay…
So, if you expect that checked exception will be thrown in your code, you better use rollbackFor
in this way:
Benchmarking
Now it’s clear. Let’s check how much we pay for the AOP magic. I wrote 4 simple methods to compare performance of insert operations using different ways to manage transactions and ORM layers:
It runs in Spring Boot project with the default configuration. You can check the source code of this benchmark out on github (gradlew transactional:run
). That’s what I’ve got:
This chart shows the best execution time from 20 attempts for 100, 1000, and 10000 inserts. As you see, @Transactional + Spring Data works almost the same as working with EntityManager directly. For 10000 inserts, the time difference between @Transactional and EntityManager was 250ms - it’s 4% of total execution time, and it’s much less than the difference between pure JDBC and EntitiyManager.
Related Posts
- 01/29 Scala testing with a human face
- 01/02 Scala with a human face
- 11/27 Dynamic bean definition for automatic FilterRegistrationBeanFactory unregistration
- 08/29 Spring @Configuration vs @Component
- 08/16 CGLIB: signer information does not match signer information of other classes
- 07/22 WebApplicationContext in the stand-alone application