I've been seeing the same problem. It comes out of the improper use of the @Transactional annotation. Here's what I was doing:
doStuff(String[] ids) {
Criteria criteria = dao.createCriteria(Widget.class); // Session still open here.
criteria.add(Restrictions.in("widgetId", ids)); // This closed the session!
...
}
It turns out that my dao class was annotated with the @Transactional
annotation. So as soon as I tried to do something with my Criteria, it first closed the transaction, which closes the session. The solution was get rid of the dao's createCriteria()
method and to add a method to the dao that does all the work with that uses the Criteria instance.
doStuff(String[] ids) {
List<Widget> = dao.getWidgetsFromIds(ids); // Do everything inside the transaction
...
}
----
// This is in the DAO:
public List<Widget> getWidgetsFromIds(String[] ids) {
Criteria criteria = dao.createCriteria(Widget.class); // Session is open here.
criteria.add(Restrictions.in("widgetId", ids)); // Session still open
...
}
The way I've structured my code, the Criteria should be an internal implmentation detail of the DAO, and shouldn't be visible to the calling methods.