Hi all
We're using Hibernate in our business application and it's doing it's job very well. However, when I implemented the search functionality, I'm getting those nasty
OutOfMemoryErrors. My approach is a bit special, but I didn't see another solution. Perhaps you might help me find the memory bug or help me improving my search-system with hibernate.
This is the way I did it:
- SearchCriterias are entered.
- Objects on the table are sought.
- Then from the retrieved Objects I extract every ID and store them in a collection. Lazy collections helps me here in speed. (I need data from child-objects but it would be very time-expensive if I would first get the objects and then do calculations with these)
- Afterwards, I go through that list of IDs and create SQL-Queries for a view I created which delivers me exactly the data I need (Objects are far to deeply nested to calculate data with children). Query example: from v_myView where id = 1 and id = 2 etc.
These queries are huge of course. But it works. I split them to portions of 1000 IDs per query in order to avoid overflows.
Now everything's fine, but...
My memory increases with every search and finally the OOME occurs.
I profiled and memory-debugged it and came to the conclusion that there are way too many
antlr.CommonAST and
org.hibernate.hql.ast.SqlNode,
.LiteralNode,
.IdentNode objects. They increase with every search almost a 100 percent. First I presumed that the Hibernate Query Cache was on, but we set the property correctly to
false in our config file. Query.setCacheable(false) didn't help either.
Has anyone experienced the same problems while searching with too many or too long queries before? Or does anyone know how to optimize our search method using hibernate?
I appreciate all your help. I tried so many things and still can't figure out what's wrong... Quite frustrating, you know.
Somewhere I read, that I should close the session factory to solve this problem (or a similar one), but even with closing, flushing or clearing every session and sessionfactory that is available, it just did not work.
Here is my set up:
Hibernate version: 3.0.5
Code between sessionFactory.openSession() and session.close():
Code:
// <-- ids retrieved and stored in foundIds (ArrayList)
int iterationStep = 1000;
int total = foundIds.size();
HashSet result = new HashSet(total);
// do several smaller queries
for(int count = 0; count < total; count += iterationStep)
{
// the upper limit of ids to fill in the query
int upperLimit = count+iterationStep > total ? total : count+iterationStep;
logger.info("from: "+count+" to (excluding) "+upperLimit);
// generates our current query with a portion of the ids
String strQuery = generateSearchOrdsQuery(foundIds.subList(count, upperLimit);
// creates the query
Query query = HibernateUtil.getSession().createQuery(strQuery);
// and executes it
result.addAll(query.list());
logger.info("subtotal: "+result.size());
}
// the query generator-method
private String generateSearchOrdsQuery(List foundIds)
{
StringBuffer hqlQuery = new StringBuffer("from VSearchOrds ");
// rem: VSearchOrds is the name of the used view
if(foundIds != null)
{
hqlQuery.append(" where ");
// now add the ids to this query
for(Iterator iter = ordsIds.iterator(); iter.hasNext();)
{
Integer foundId = (Integer)iter.next();
hqlQuery.append(" id = " + foundId.toString() + " or ");
}
hqlQuery = new StringBuffer(hqlQuery.substring(0, hqlQuery.length()-3)); // to remove the last ''or''
}
return hqlQuery.toString();
}
Full stack trace of any exception that occurs: java.lang.OutOfMemoryError (no stack trace available)
Greetings from Switzerland! (I'll send you a postcard, if you can help me solving my problem =)