Categories
Java

Hibernate 4 with JTA Transactions

The following problem occurred when I was migrating from Hibernate 3 to Hibernate 4.2.3. Scrollable result sets were suddenly throwing exceptions:

org.hibernate.exception.GenericJDBCException: could not advance using next()
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
	at org.hibernate.internal.ScrollableResultsImpl.next(ScrollableResultsImpl.java:121)
...
Caused by: java.sql.SQLException: Operation not allowed after ResultSet closed
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
	at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:804)
	at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:6986)
	at org.hibernate.internal.ScrollableResultsImpl.next(ScrollableResultsImpl.java:116)

It turned out after 3 hours of debugging and research that Hibernate’s 4 JTA implementation relies on having a transaction started not via JTA User Transaction but through Hibernate’s own Session object. The correct configuration in such cases is simply to use CMTTransactionFactory as transaction factory class:

1
2
3
4
5
6
7
8
9
10
11
12
13
<hibernate-configuration>
   <session-factory>
      <!-- How to find the Transaction -->
      <property name="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory</property>
 
      <!-- How to produce transaction -->
      <property name="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.JOTMJtaPlatform</property>
 
      <!-- Session context with JTA -->
      <property name="current_session_context_class">jta</property>
      ...
   </session-factory>
</hibernate-configuration>

As explanation: The error is primarily caused by a bug in JTA implementation within Hibernate (it does not synchronize Hibernate’s with JTA’s transaction object). It occurs mainly when you use the Entity Manager. In above’s exception, a second retrieval was executed within object iteration which caused Hibernate to think that there is no active transaction and hence, close any previous statements. That’s why the Scrollable Result loses its session.

The solution was published first by Koen Serneels. Many thanks!