Hibernate is the popular object relation mapping implementation. This feature makes it special among the developers and in this tutorial we will see the best practices to create better Hibernate applications.
Table of Contents
- Object-Relational Mapping or ORM is the programming technique to map application domain model objects to the relational database tables
- Hibernate is a Java-based ORM tool that provides a framework for mapping application domain objects to the relational database tables and vice versa. It provides a reference implementation of the Java Persistence API that makes it a great choice as an ORM tool with benefits of loose coupling
- A framework that provides the option to map plain old Java objects to traditional database tables with the use of JPA annotations as well as XML based configuration
- A framework that provides the data query and retrieval facilities and is purely used for the data persistence (i.e. to store/retrieve data from the database)
- A framework that internally uses the
JDBCAPI to interact with the database. It hides the internal
JDBCimplementations from the end users
There are 4 layers in the Hibernate architecture i.e. Java Application Layer, Hibernate Framework Layer, Backend API Layer, and the Database Layer. Let’s understand the diagram of Hibernate architecture.
For creating the first Hibernate application, we must know the elements of the Hibernate architecture. They are as follows:
SessionFactory is a factory of session and client of
Connection Provider. It holds second level cache (optional) of data.
|The session object provides an interface between the application and data stored in the database. It is a short-lived object and wraps the
JDBC connection. It is a factory of
Criteria and holds the first-level cache of data. The
Session interface provides methods to
DELETE the objects.
|The transaction object specifies the atomic unit of work and is an optional parameter in the Hibernate framework.
|It is a factory of
JDBC connections and abstracts the application from
DataSource. It is an optional parameter in the Hibernate framework.
|It is a factory of
Transaction and is again an optional parameter in the Hibernate framework.
There are many advantages of using the Hibernate framework, e.g.
- Hibernate framework is open source and lightweight
- The performance of the Hibernate framework is fast and supports smart fetching techniques because of the internal caching mechanism
- Hibernate framework provides the facility to create the database tables automatically
- With the help of
HQL(Hibernate Query Language), the generated
SQLqueries are independent of databases
- Provides query facilities to fetch the data from multiple databases, and supports transaction management and automatic key generations
- Provides APIs for storing and retrieving the Java objects directly to and from the database
- The framework takes care of the mapping Java classes to database tables using XML files or annotations
Let us explore the different Hibernate strategies that can be adopted to improve the performance of an application.
While writing SQL Select query, developers can choose the columns they need for implementation. JPA and Hibernate support specific columns than just entities. There are of 3 types and each has its own usage.
An entity is the most common implementation. Developers can use it if they need all entity attributes or to perform the SQL Update or Delete operations that affect a minimal entity number.
2.1.2 Model class a.k.a POJO
The POJO is similar to Entity class but it represents a specific record in the database.
List list= em.createQuery(“SELECT
Bookdetails(book.isbn, book.author) FROM Bookdetails book”, Bookdetails.
ORM frameworks offer multiple options to create an SQL query that matches their requirement. Let us understand them one by one.
2.2.1 find() method
This method is the easiest implements to find a record from the database by its primary key. This method not only provides security and performance benefits. It is also:
- Checking the record in the 1st and 2nd level cache to save the costly trips to the database
- Avoiding the SQL injection problems
2.2.2 Java Persistence Query Language (JPQL)
The Java Persistence Query Language (JPQL) is similar to SQL queries but it executes on entity class and their relations but not directly on database tables. This approach offers low and moderate complexity.
TypedQuery tq = em.createQuery(“SELECT book FROM Book book JOIN book.author WHERE book.title = :title”, Book.
2.2.3 Criteria API
The Hibernate’s Criteria API generates dynamic queries at runtime. Developers can use this if the query structure depends on user input. Let us understand this with the help of an example.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery q = cb.createQuery(Book.
Root book = q.from(Book.
SetJoin join= book.join(Book.
2.2.4 Native SQL Queries
Native Queries provide developers the way to write and execute the database statements. This is the best way to write complex queries in the Hibernate framework.
Myclass e = (Myclass) em.createNativeQuery(“SELECT * FROM myClass e WHERE e.name =“abc“, Myclass.
Using parameter bindings for the query offers several advantages over the regular SQL query strings.
- No SQL injection
- Automatic mapping of query parameters to its correct type
- Increased performance
These are represented by a number starting with 1 and prefixed with
Query q = em.createNativeQuery(“SELECT c.firstname, c.lastname FROM Employee c WHERE c.id = ?”);q.setParameter(
Eager loading the records from the database is another reason that affects Hibernate performance.
(mappedBy = “authors”, fetch = FetchType.EAGER)
Set books =
The framework fetches the related entities from the database based on the relationship and the defined fetch mode. This result in confusion as hibernate fetches the related entities data which may be required from the given test case. To overcome this issue developers should use the fetching mode as
Jdbc allows batching the multiple SQL statements and sending them to the database in a single request. This approach saves multiple trips for all the SQL operations and reduces the response time.
Hibernate use the existing database features to auto-generate the unique id identifier otherwise called as Primary key column values. The following code snippet will help us understand the use of
(name = “id”, updatable =
, nullable =
Here are some points that can help us while using the Hibernate Framework:
- Prefer using
session.load(). Load always returns the proxy to avoid getting
- Always set
lazy=truefor collection mappings and use
CriteriaAPI to retrieve collections
- Use surrogate id in the data model instead of Composite Keys and override
hashCodemethod using the business key to identify uniqueness
RuntimeExceptionnever catch them at the business layer and have them be propagated to UI Layer
SQLQuery cache for read-only data
- Many-One Mapping should preferably have
lazy=falseand One-Many should have
lazy=true. To avoid N+1 Query problem in Hibernate use Eager Fetching technique or Batch settings
- Don’t retrieve too much data in one
SQLquery and use Paging, Fetch Strategy, and carefully use the
Jointo get the needed data
- Use 2nd Level Caching technique for read-only data
- Do not perform bulk operations with Hibernate
That’s all for this post. Happy Learning!!
Following is an extract of good practices in Hibernate. Developers can use these tips to implement in their application and offer better performance. I hope this article served you whatever you were looking for.