In one of my DAO objects, a method exists where a scrollable result set is created based on an entity object and some criteria and then the result set is iterated over to perform some necessary business logic on the data retrieved. The purpose of this code was to iterate over a large result set of data but allowing the objects to be removed from the session after no longer being needed to avoid using too much heap memory. Code here:
Code:
Criteria criteria = session.createCriteria(MyObject.class);
// apply restrictions here
ScrollableResults results = criteria.scroll();
while(results.hasNext()) {
MyObject obj = (MyObject) results.get(0);
// work with MyObject
session.evict(obj);
}
results.close();
The problem with this approach is that now the business logic exists in the DAO layer which I feel it belongs in the service layer with all the other business logic. In order to attack the problem I chose to write a simple wrapper class based on a simple interface so that the result sets could be returned from the DAO layer and the Service layer could use this interface wrapper to iterate the results and perform the business logic as shown below:
Code:
public interface IResults<T> {
boolean hasNext();
T next();
void close();
}
public class ResultsHibernate<T> implements IResults<T> {
public ResultsHibernate(ScrollableResults results, Session session) {
this.results = results;
this.session = session;
this.counter = 0;
}
public boolean hasNext() {
return(results.next());
}
public T next() {
return((T)results.get(0));
}
public void Close() {
results.close();
}
}
At the DAO layer, it changes the method so it looks like:
Code:
Criteria criteria = session.createCriteria(MyObject.class);
// apply restrictions here
return(new ResultsHibernate(criteria.scroll(), session));
The problem is when
next() is called on the scrollable result set it says that it is now closed. Why would the result set be closed when inevitably its the same code as it being inside the DAO layer, except it's now being wrapped in another class to be used inside the service layer or have I overlooked something so simple here??
Exception: org.hibernate.exception.GenericJDBCException: could not advance using next()
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed.