We are using Hibernate 4.1.1.Final with Spring's JtaTransactionManager, LocalSessionFactoryBean and SpringSessionContext. We have set:
Code:
hibernate.transaction.jta.platform=org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform
hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory
We need to use the criteria and query scroll() functionality in order to process large result sets in a memory efficient manner. The code can be boiled down to the following snippet...
Code:
ScrollableResults results = getCurrentSession().createQuery("some hql....").scroll();
while (results.next()) {
process(results.get(0));
}
results.close();
However since upgrading Hibernate (from 3.6.7) (and replacing Spring's HibernateTemplate with the recommended sessionFactory.getCurrentSession() calls) we have had a problem with those cases that access the Hibernate session during the iteration (e.g. process(...) does getCurrentSession().get(entityName,id)).
On the subsequent call to results.next() we get the following exception thrown...
Code:
org.hibernate.HibernateException: proxy handle is no longer valid
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.errorIfInvalid(AbstractProxyHandler.java:63)
at org.hibernate.engine.jdbc.internal.proxy.AbstractResultSetProxyHandler.continueInvocation(AbstractResultSetProxyHandler.java:84)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at $Proxy161.next(Unknown Source)
at org.hibernate.internal.ScrollableResultsImpl.next(ScrollableResultsImpl.java:116)
What seems to happen is that SessionImpl.afterOperation(boolean) (called when the get of the entity or whatever completes) thinks that there is no active transaction (though there *is* an active JTA transaction) and so it closes the scrollable resultset.
In Hibernate 4.1.1, org.hibernate.engine.transaction.internal.jta.JtaTransaction.isActive() is used to determine whether there is a transaction active. However this immediately returns false if there is no local (?) tx. It is as if we should be calling session.beginTransaction() to set an active local tx even though our transactions are JTA and managed declaratively.
Not sure whether this is an issue with Hibernate or with Spring. It just seems that this ought to work.
Any ideas? (Let me know if you need more info.)