Hibernate Tips to Boost Your Performance

In this blog, I am going to point out the most common Hibernate performance tips, which will enhance your code and accelerate the data access layer in your applications.

In a production environment, abnormal conditions may affect our systems. Chaos engineering lets you cope with this problem in a safe way. Learn how it works on our blog post Chaos Engineering for Resilient Software

We know that starting with JPA and Hibernate is quite easy but it’s really important to understand how to find performance problems and how to fix them correctly.
Here are the basic tips to achieve that.

Tip 1- Try to Use Lazy Fetching

FetchType defines when Hibernate must initialize its associations. We can specify this with the fetch attribute and @OneToMany, @ManyToOne, @ManyToMany, and @OneToOne annotations.
For example, suppose we have a class named Author, that has a list of books associated. This class is what we call an entity in Hibernate. An entity represents a row of a table, so:

Hibernate Tips
Hibernate Tips

Hibernate loads every entity association when the entity itself is loaded into the session. That means that when an Author is loaded, it also does entity Book. So, not only Author SQL is executed in the database, but Book SQL is too. This is really inefficient!
To avoid this problem, we must use the FetchType.LAZY command which delays entity relationships initialization and loads them only when they are called explicitly in the code.
FetchType.LAZY is defined by default in every ToMany option but is not defined in ToOne options, so be careful with this.

Tip 2- Select Exactly The Rows You Need

If we select too many rows from the database, our application will surely slow down. One of the reasons is that JPQL (Hibernate uses JPQL query language and JPA Java Persistence API for data access) does not allow very useful SQL commands like OFFSET and LIMIT.
Nevertheless, we can limit somehow the exact row quantity that will be returned with Query interface and setMaxResults and setFirstResult operations.
For example, in this case, we are selecting only the five first authors ordered by id:

Hibernate Tips
Hibernate Tips

Tip 3- Always use Binding Parameters

Binding parameters are very simple to use. Hibernate does every needed data conversion automatically and what’s more scapes Strings automatically too, which can prevent SQL injection. This is truly helpful when we are implementing high-performance applications.
Generally, we have the same queries along with our code, with a variety of values in the where statement. Hence, when we use binding parameters we are helping Hibernate to identify and optimize those queries.
This example is quite simple with one parameter id:

Hibernate Tips
Hibernate Tips

Tip 4- Use Stored Procedures

It is common to implement all application logic in a logic layer, but sometimes it is better to use Stored Procedures into the database, usually when we have to operate with large amounts of data. To use them we only need to call the procedure into our code.
We can use standard operations in JPQL queries, like size() for example:

Hibernate Tips
Hibernate Tips

With JPA function function we can call our own specific database functions, for example, calculate():

Hibernate Tips
Hibernate Tips

Tip 5 – Avoid Flush Operation

Executing flush into the current session forces Hibernate to synchronize session state in memory, thus, that forces to execute all SQL queries that the session is managing at that time. This clearly slows down our application because now Hibernate is not able to optimize those queries anymore.
Hibernate uses AUTO-flush, so it stores all entities in persistence context and delays write SQL executions until really necessary. This allows Hibernate to combine multiple update operations to the same entity into one SQL update, as well as merging identical queries through JDBC batching and avoiding duplicate queries which would return an entity that is already in the current session.

Tip 6 – Do Not Use Hibernate for Everything

Hibernate and JPA provide great support for CRUD operations like read, write and update to few database rows. But when we need to create really complex queries, analyze or create operations over a huge amount of rows it is not a good idea to use them.
It is highly recommended to use another framework, much more like SQL, to avoid object-relational mapping. This framework can be jOOQ.

Tip 7- Updating Many Rows

Generally, when we use java objects we update or delete entities one by one. But this is not a good solution when we have too many rows.
Hibernate does not have an operation that can update or delete multiple rows at once.
To manipulate a group of entities, we can load them from the database, we can operate over them individually, and finally, SQL are generated for each one of them.
Thus, instead of updating 100 rows with 1 query, Hibernate uses at least 101 queries!!

Luckily we can resolve this issue with JPQL, native SQL, or Criteria queries.

But, be careful when using Criteria queries, because queries are executed directly into the database without using entities. This drives into better performance but also evades natural entities’ life cycle, so Hibernate can not update its caches properly.

To solve this, you can call flush method and force Hibernate to write pending changes into the database, and after that, you can call the clear method that frees entities from persistence context. After doing those calls, you can execute massive updates.
For example (em is the EntityManager which provides Hibernate and it is to manage entities):

Hibernate Tips
Hibernate Tips

Tip 8- Don’t Use Entities For Read-Only Queries

DTO pattern purpose is to create a plane POJO object with attributes from different sources or tables and allow us to concentrate on a single class for better manipulation between server and client.

DTOs are faster than entities, even when we are reading the same columns from the database.

Entities may be part of a business domain, your persistence context manages the entities. Thus, they can implement behavior and be applied to different use cases within the domain. DTOs are used only to transfer data from one process or context to another.

You must have in mind that Hibernate and other JPA implementations keep entities into a first-level cache. That must sound good because it prevents duplicate queries which are necessary for query optimization. But, first-level cache management is not trivial and takes time, so that could be a problem if we are selecting thousands of entities, even with hundreds of them.

Thus, when using entities we generate a huge overweight that can be avoided using DTOs.

Entities are really good for writing operations.

Hibernate and other JPA implementations manage state entities and generate necessary SQLs for updating records into the database
In this example we are updating the first name attribute of an entity:

Hibernate Tips
Hibernate Tips

 

DTOs are better for reading operations

If we are reading data it is not necessary to manage states, so better use DTOs
Example with JPQL, and DTO BookValue:

Hibernate Tips
Hibernate Tips

 

Tip 9- Use Statistics

You can enable the statistics component, which measures queries execution time and what’s more provide a summary of executed queries and execution time for each session. Before using this, you should review the indexes you have created, and add or drop them if convenient.
This is really helpful to check overall application functioning and helps to identify sessions that could contain performance issues.
Don’t use this in a production environment!!!
You can activate statistics with hibernate.generate_statistic property

Hibernate Tips
Hibernate Tips

Additionally, you must configure DEBUG log level with org.hibernate.stat.
Hibernate will write into the log the executed SQL query, the returned number of rows, and the execution time…

Hibernate Tips
Hibernate Tips

As you can see, there are a lot of tiny details that can slow down your application, but they can be easily avoided, and finally create a high-performance persistence layer using these tips.

In a production environment, abnormal conditions may affect our systems. Chaos engineering lets you cope with this problem in a safe way. Learn how it works on our blog post Chaos Engineering for Resilient Software

You may also like

No results found.

Menu