The Constructor based HQL shows you how to create query select new object in hibernate for improving performance. Normally, almost of developer don’t bother retrieving the whole entity with all its properties. While they don’t really need all of them in a particular case. For example, we have a single entity with 25 properties, and we just need a few to display to user. In case, if we execute the query to get thousands of records, the unused fields will make us heavily jamming and lead to a huge performance hit in our application.
Other interesting posts you may like
HQL/JPA provides us with a select new constructor call to deal with the above issue. We create a simple Constructor based HQL like below:
1 |
String sql = "select new Student(s.id,s.name) from Student s where s.id=:studentId"; |
In fact, we often use Constructor based HQL for reporting queries, which allows the us to select aggregated values as well. To do this, we should create a bean that will store the aggregated values of query. This class is just poor java class. It is not a entity neither doesn’t put it in hibernate configuration file. The Constructor based HQL with aggregated values looks like below:
1 |
String sql2 = "select new com.javabycode.hibernate.model.StudentExtended(s.name,count(s)) from Student s where s.id=:studentId"; |
Reporting Queries just select the used fields so that it avoid the overhead of retrieved entities getting cached in the persistent context. It makes a huge improvement in the performance compared to the traditional retrieval technique with Hibernate.
Let’s create example to clarify how Constructor based HQL works.
Create project directory structure
In this Constructor based HQL tutorial, we will create the final project directory structure like below:
Create a program for testing
This program will query student data from database by using Constructor based HQL. Here we get the available student with id=33.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package com.javabycode.hibernate; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import com.javabycode.hibernate.model.Student; import com.javabycode.hibernate.model.StudentExtended; public class HibernateConstructorHQLExample { public static void main(String[] args) { SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); String sql = "select new Student(s.id,s.name) from Student s where s.id=:studentId"; Query query = session.createQuery(sql); query.setLong("studentId", 33L); List<Student> list = (List<Student>)query.list(); for (Student student : list) { System.out.println(student); } String sql2 = "select new com.javabycode.hibernate.model.StudentExtended(s.name,count(s)) from Student s where s.id=:studentId"; Query query2 = session.createQuery(sql2); query2.setLong("studentId", 33L); List<StudentExtended> list2 = (List<StudentExtended>)query2.list(); for (StudentExtended student2 : list2) { System.out.println(student2); } } } |
Run above the main like java application and produce the output like below:
1 2 3 4 |
Hibernate: select student0_.id as col_0_0_, student0_.NAME as col_1_0_ from STUDENT student0_ where student0_.id=? Student [id=33, name=David Villa, enteringDate=null, nationality=null, code=null] Hibernate: select student0_.NAME as col_0_0_, count(student0_.id) as col_1_0_ from STUDENT student0_ where student0_.id=? StudentExtended [name=David Villa, count=1] |
As you can see the above program. It’s quite easy to create Constructor based HQL with aggregated values.
Noticed that the constructor-based HQL query will return all instances in transient state. It means that it doesn’t return persistent entity instances to the persistence context cache.
Download complete source code, please click link below
HibernateConstructorHQLExample.zip (358 downloads)