Browse DevX
Sign up for e-mail newsletters from DevX


Hibernate Criteria API: Multi-Criteria Search Made Easy

The Hibernate Criteria API, a powerful and flexible alternative to traditional HQL queries, makes writing all those tricky multi-criteria search functions—as well as dynamic queries in general—much easier.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

ulti-criteria search functionalities, which allow combinations of many optional criteria fields, are common in modern Web-enabled business applications (see Sidebar 1. When to Use Multi-Criteria Searches). An example of this functionality is an online accommodations database (see Figure 1) that allows users to search accommodations by country, availability, type (hotel, bed and breakfast, etc.), and capacity. All the criteria are optional, and the user may use any combination of criteria.

Click to enlarge
Figure 1: A Multi-Criteria Search Screen

The traditional approach for a Hibernate developer to enable this sort of functionality generally involves building an HQL (Hibernate Query Language) query on the fly, based on the search criteria the user entered. Next, he or she uses this query string to create a Hibernate Query object and then sets the non-null parameter values. The code looks something like this:

... if (startDate != null) { queryBuf.append(firstClause ? " where ": " and "); queryBuf.append("a.availabiliyDate >=:startDate"); parameters.put("startDate",startDate); firstClause = false; } ...

(See Listing 1 for a full example. Note that the model has been simplified for the sake of readability. Accommodation availability data would normally be stored in a separate table, of course.)

Listing 1. A Traditional Approach for Building Multi-Criteria HQL Queries

public List searchAccommodation(Date startDate, Date endDate, Country country, AccommodationType type, Integer capacity) Map parameters = new HashMap(); boolean firstClause = true; StringBuffer queryBuf = new StringBuffer("from Accommodation a "); if (startDate != null) { queryBuf.append(firstClause ? " where " : " and "); queryBuf.append("a.availabiliyDate >= :startDate"); parameters.put("startDate",startDate); firstClause = false; } if (endDate != null) { queryBuf.append(firstClause ? " where " : " and "); queryBuf.append("a.availabiliyDate <= :endDate"); parameters.put("endDate",endDate); firstClause = false; } if (country != null) { queryBuf.append(firstClause ? " where " : " and "); queryBuf.append("a.country = :country"); } if (type != null) { queryBuf.append(firstClause ? " where " : " and "); queryBuf.append("a.type = :type"); } if (maxCapacity != null) { queryBuf.append(firstClause ? " where " : " and "); queryBuf.append("a.capacity >= :capacity"); } String hqlQuery = queryBuf.toString(); Query query = session.createQuery(hqlQuery); // // Set query parameter values // Iterator iter = parameters.keySet().iterator(); while (iter.hasNext()) { String name = (String) iter.next(); Object value = map.get(name); query.setParameter(name,value); } // // Execute the query // return query.list(); }

This approach is cumbersome and error-prone. It is also risky in a team-development context, as inexperienced developers will often take dangerous short-cuts using this approach. During code review, I've often come across multi-criteria search functions using error-prone String concatenation, direct use of query parameters in the query string, and so on:

... if (startDate != null) { if (firstClause) { query = query + " where "; } else { query = query + " and "; } query += " a.availabilityDate >= '" + startDate + "'"; } // And so on...

So, is there better way? Yes, there is: the Hibernate criteria API, a powerful and elegant technique for complex, dynamic search functionalities. Using the online accommodations database cited previously, this article examines the criteria API solution and its benefits.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date