I've done this exact same thing for searching on my site, except I don't use the Criteria object. However, I do use the Criteria in 99% of all my other db related options, so I might be able to offer some insight as to what I've done.
First, my 'search engine' presents the same object to the view across different tables as well as sections. I search across content as well as other non-content tables that contain various demographics on companies for our industry. In order to get the back end correct, I had to create an Interface and Wrapper impl objects so the db would always have one type of object to return. In this object, I wrap the individual result rows, the current index number of what page in the db I'm on (offset), the total count of rows found, and the page size the user has specified. And this approach has served me well so far. It has allowed me the typical search results paradigm that everyone expects on a web site.
I have two forms: a simple one field search everything form, and a 'advanced' form that will pick across our company demographics as well as content tables. To get the best speed out of my search, I actually use jdbc->stored proc, but I could have easily used Criteria objs.
From the form I have two objects, based on the search type:
Code:
SimpleQuery
AdvancedQuery
These two objects have various user specified input values like offset, row limit, and the search terms entered. They also have two fields:
Code:
<type>Query
Original<type>Query
(replace type w/Simple or Advanced)
These methods provide in and out query conversion. My controller will pass the various request params and either of these objects to the necessary parser object. The parser is responsible for, obviously, parsing out the key words and taking care of terms like NOT, AND, etc. It will also deal with quotes, parens, and wildcards. Once I have the terms of a query parsed out, I either assign them to other minor objects where I can associate a condition to them or I just have a List of the terms that I can go thru on the DAO level. If you're interested more in parsing, then there's a pretty good book called 'Building Parsers With Java' (ISBN:0201719622 ) - my parsers are all based on concepts from this book.
At the back level I have a SearchDAO that handles the construction of the query. Now, to get to what you're interested in. I would think it would be possible somwhere in the chain from user input to DAO level that you can specify a table name somewhere. Once you have the name, it could be easy to specify the criteria to pick off that table like so:
Code:
SearchDAO:
public CommonResultInterface search(QueryObject queryObj){
// We'll use two objects that implement CommonResultInterface
// UserResults
// GroupResults
// Whatever code u use to get session here
// I'm assuming the table name has an associated object name
Class class = Class.forName(queryObj.getTable());
Criteria crit=session.createCriteria(class);
if(queryObj.getTable().equals("com.company.entity.Users")){
crit.add( Expression.eq("name", queryObject.getParam("name")) );
crit.addOrder( Order.asc("groupId") );
List list = crit.list();
UserResults userResults = new UserResults();
// Set the number of results we're returning here
// I also run separate count queries before this step to set a
// 'total records' value for the user and whatever else I need
userResults.setResultsReturned(list.size());
userResults.setResultType("USER");
Iterator it = list.iterator();
while(it.hasNext()){
// This is where you could get specifc props from your user table
// or even just add the Users object itself to the results
UserObjectWrapper uobj = new UserObjectWrapper();
Users user = (Users)it.next()
uobj.setName(user.getName());
uobj.setLogin(user.getLoginId());
userResults.add(uobj);
}
// Do whatever here to close your hibernate session
return users;
}else if(queryObj.getTable().equals("com.company.entity.Groups")){
crit.add( Expression.eq("grpId", queryObject.getParam("groupName")) );
List list = crit.list();
// similar code as above here
}
}
Now, this is all kinda off the cuff, but I do similar things in my code. I think the main thing is to be able to define the proper Interface (if possible) so you can use one method to do your searching. This has worked great for me as in my interface I have a mandated field called
Code:
resultType
that I check in the view and based on that, display the necessary results. This could also be checked by the controller and then based on this, it could return a specific view that only dealt with displaying specifc info.
Also, you'll have to make sure that if you want to use different tables as I've sorta shown above, you'll just have to get the proper class from the entity/table name (remember, they have to be fully qualified names as per the java Class documentation). This could include setting vals on the form or somewhere in the query generation - but it's pretty easy to specify that as I've shown. Granted, if you have a large number of tables to query across, then the above code is prob not the best approach. It could, though, maybe point you in the right direction.
Hope this helps,
- Jason