Wednesday 11 September 2013

Don't use HibernateTemplate.setMaxResults()

Say you have an EmployeeDao class and write a method to return the top N salary employees.

You implement it with HibernateTemplate.setMaxResults().

     public List<Employee> findTopSalaryEmployees(int maxResults) {  
         HibernateTemplate ht = getHibernateTemplate();  
         ht.setMaxResults(maxResults);  
         return ht.find("from Employee e order by e.salary desc");  
     }  

Then you need to write a second method to return all employees.

     public List<Employee> findAllEmployees(){  
         return getHibernateTemplate().find("from Employee e");  
     }  

When you test them separately, they are working fine. However, when they are tested together, a problem might occur.  You may find the findAllEmployees() only returns part of the employees.

Why?

Because the HibernateTemplate object is shared across different methods and when the max results variable is set, it doesn't get reset at the end of the method.

One of the solutions is to reset it to 0 at the end of the method. But I don't like this solution because developers can easily forget to do so.

I would suggest using HibernateCallback:

     public List<Employee> findTopSalaryEmployees(final int maxResults) {  
         List<Employee> list = getHibernateTemplate().execute(  
             new HibernateCallback<List<Employee>>() {  
                 @Override  
                 public List<Employee> doInHibernate(Session session)  
                         throws HibernateException, SQLException {  
                     Query query = session.createQuery("from Employee e order by e.salary desc");  
                     query.setMaxResults(maxResults);  
                     return query.list();  
                 }  
             });  
         return list;  
     }  
It is indeed a bit longer than the previous solution, but you don't need to reset the max result value to 0 at the end of the method.