APIFinder
   The essential directory of application programming interfaces
Submit an API
DevX
Function
Language/OS
Contribute
About
Browse DevX
advertisement
Log In | Register
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 functionsas well as dynamic queries in generalmuch easier. 
February 22, 2008

advertisement
Multi-criteria search functionalities, which allow combinations of many optional criteria fields, are common in modern Web-enabled business applications. 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.

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 below 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.

Introducing the Hibernate Query API
The Hibernate Query API lets you write the previous 36-line example in Listing 1 using just 17 lines of quite readable code (see Listing 2 for the full example):


...
Criteria criteria
= session.createCriteria(Accommodation.class);
if (startDate != null) {
criteria.add(Expression.ge("availabilityDate",
startDate);
}
if (endDate != null) {
criteria.add(Expression.le("availabilityDate",
endDate);
}
// and so on

Listing 2. Using the Hibernate Criteria API for Multi-Criteria Queries


public List searchAccommodation(Date startDate,
Date endDate,
Country country,
AccommodationType type,
Integer capacity)
Criteria criteria
= session.createCriteria(Accommodation.class);
if (startDate != null) {
criteria.add(Expression.ge("availabilityDate",
startDate);
}
if (endDate != null) {
criteria.add(Expression.le("availabilityDate",
endDate);
}
if (country != null) {
criteria.add(Expression.eq("country",country);
}
if (capacity != null) {
criteria.add(Expression.ge("capacity",capacity);
}
if (type != null) {
criteria.add(Expression.eq("type",type);
}
List results = criteria.list();
//
// Execute the query
//
return query.list();
}

Continue reading article on DevX.com...

John is the principal consultant at Wakaleo Consulting, a New Zealand-based consulting company specialising in Enterprise Java, Web Development, and Open Source technologies. Well known in the Java community for his many published articles, and as author of Java Power Tools, John helps organisations to optimize their Java development processes and infrastructures. and provides training and mentoring in open source technologies, SDLC tools, and agile development processes.


Hibernate Criteria API
Hibernate Criteria is a simplified API for retrieving entities by composing Criterion objects. This is a very convenient approach for functionality like a "search" screen where there is a variable number of conditions to be placed upon the result set.
Provider: Red Hat Middleware   Cost: 0