Object-relational Mapping Using JPA, Hibernate and Spring Data JPA. Comparing the performance of persisting entities
Comparing the performance of persisting entities
We’ll analyze the performances of persisting entities through the three approaches, considering the number of needed dependencies and JAR files to run the project, the number of lines of code to write, and the execution times.
Working with a particular framework will mean that its classes have to be imported into our code and also have to be accessible on the classpath. Fewer classes on the classpath will also mean a lower memory footprint.
Hibernate
|
JPA
|
Spring Data JPA
|
|
Maven dependencies |
1
|
1
|
2
|
Needed JAR Files |
22
|
29 (22 from Hibernate)
|
62
|
Lines of code |
47
|
57
|
29
|
Table 1 Maven dependencies, JAR files and lines of code to be written
Number of records
|
Hibernate
|
JPA |
Spring Data JPA
|
1000 |
1138 | 1127 | 2288 |
5000 |
3187 | 3307 | 8410 |
10000 | 5145 | 5341 | 14565 |
20000 | 8591 | 8488 | 26313 |
30000 | 11146 | 11859 | 37579 |
40000 | 13011 | 13300 | 48913 |
50000 | 16512 | 16463 | 59629 |
Table 2 Insert execution times by framework (times in ms)
Number of records
|
Hibernate
|
JPA
|
Spring Data JPA
|
1000 |
706 |
759 |
2683 |
5000 |
2081 |
2256 |
10211 |
10000 |
3596 |
3958 |
17594 |
20000 |
6669 |
6776 |
33090 |
30000 |
9352 |
9696 |
46341 |
40000 |
12720 |
13614 |
61599 |
50000 |
16276 |
16355 |
75071 |
Table 3 Update execution times by framework (times in ms)
Fig. 3 Update execution times by framework (times in ms)
Number of records
|
Hibernate
|
JPA
|
Spring Data JPA
|
1000 |
251 |
232 |
338 |
5000 |
214 |
192 |
401 |
10000 |
223 |
210 |
718 |
20000 |
246 |
248 |
1099 |
30000 |
276 |
308 |
1475 |
40000 |
311 |
297 |
1964 |
50000 |
362 |
344 |
2252 |
Table 4 Retrieve execution times by framework (times in ms)
Table 4 Retrieve execution times by framework (times in ms)
Number of records
|
Hibernate
|
JPA
|
Spring Data JPA
|
1000 |
584 |
551 |
2430 |
5000 |
1537 |
1628 |
9685 |
10000 |
2992 |
2763 |
17930 |
20000 |
5344 |
5129 |
32906 |
30000 |
7478 |
7852 |
47400 |
40000 |
10061 |
10493 |
62422 |
50000 |
12857 |
12768 |
79799 |
Table 5 Delete execution times by framework (times in ms)
Fig. 5 Delete execution times by framework (times in ms)
Conclusions
The three approaches provide different performances from the points of view that were under analysis. The ease of development and the code reduction of Spring Data JPA is impressive (half of the number of lines of code of JPA), but it comes at a price. It requires more dependencies and more JAR files on the classpath (almost 3 times more than for Hibernate). The JPA solution needs all the Hibernate dependencies, plus its own.
There are remarkable notes regarding the execution times. Hibernate and JPA go head to head, the graphics of their times almost overlap for all four operations (insert, update, retrieve and delete). Even if JPA comes with its own API on top of Hibernate, this additional layer introduces no overhead.
For Hibernate and JPA, the update and delete execution times decrease in comparison with the insert execution times. On the contrary, the Spring Data JPA update and delete execution times increase in comparison with the insert execution times.
For Hibernate and JPA, the retrieve times grow very slowly with the number of rows. The Spring Data JPA retrieve execution times strongly grow with the number of rows.
Using Spring Data JPA is justified in particular situations: the project already uses the Spring framework and needs to rely on its existing paradigm (e.g. inversion of control, automatically managed transactions); there is a strong need to decrease the amount of code and thus shorten the development time; the number of manipulated rows at a time is small.
Summary
This article has focused on alternatives for working with a database from a Java application: JPA, Hibernate native, and Spring Data JPA and provided examples for each of them.
We implemented Java persistence code using three alternatives: JPA, Hibernate native, and Spring Data JPA.
We created a persistent class and its mapping with annotations.
Using JPA, we implemented the configuration and bootstrap of a persistence unit, and how to create the EntityManagerFactory entry point. Then we called the EntityManager to interact with the database, storing and loading an instance of the persistent domain model class.
We demonstrated some of the native Hibernate bootstrap and configuration options, as well as the equivalent basic Hibernate APIs, SessionFactory, and Session.
We examined how we can switch between the JPA approach and the Hibernate approach.
We implemented the configuration of a Spring Data JPA application, created the repository interface, then used it to save an instance of the persistent class.
We finally compared and contrasted these three approaches: JPA, Hibernate native, and Spring Data JP using a few criteria: the number of needed dependencies, the number of JAR files on the classpath, the number of lines of code to be written, and the execution times for batch processing (insert, update, retrieve and delete operations).
Pros
|
|
Hibernate
|
Fewest needed JAR files
Less memory footprint |
JPA
|
Easy to switch to another persistence provider
No overhead compared with native Hibernate |
Spring Data JPA
|
The fewest lines of code
Highest development speed Automatic management of transactions |
Table 6 Pros of each of the three approaches
Cons |
|
Hibernate
|
Hard to replace with another persistence provider
|
JPA
|
The largest amount of code to be written
|
Spring Data JPA |
Big overhead, slowest of all frameworks for batch operations |