New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hibernate 4 Autoflush does not work with Spring OpenSessionInViewInterceptor [SPR-13848] #18421
Comments
Juergen Hoeller commented So it sounds like this would affect any such early opened Sessions? All that Juergen |
Christof Patzwald commented Hello Jürgen, public class KkhOpenSessionInViewInterceptor extends OpenSessionInViewInterceptor {
} Now, after having searched for the properties available in Hibernate 4 once more, and after performing some tests with different properties, we found the property hibernate.current_session_context_class. We tested this property with jta and thread. This seems to connect the former session to the session within the transaction. Now the autoflush is being performed correctly when using the defined OpenSessionInViewInterceptor. |
Juergen Hoeller commented So this indicates that Hibernate's out-of-the-box Juergen |
Bjørn Hilstad commented We have run into this problem when migrating an application to Spring 4.x + Hibernate 4.x. |
Juergen Hoeller commented I'm afraid I have no further insight here either. Hibernate 5 came with lots of internal refactoring, so I'm not surprised it works differently there. Since Hibernate 4.x isn't supported by Red Hat anymore, we have no intentions to spend extra cycles on this from our side either. I strongly recommend an upgrade to Hibernate 5.1 or 5.2 at this point; even Hibernate 5.3 is just around the corner. With Spring Framework 5.0, we are more or less enforcing Hibernate 5.0+; with Spring Framework 4.3.x, we keep supporting Hibernate 4.2 and 4.3 but only on a best-effort basis. |
Christof Patzwald opened SPR-13848 and commented
Hibernate 4 Autoflush does not work with Spring OpenSessionInViewInterceptor
We found a Bug while migrating our applications with Spring 3.0.5 and Hibernate 3.6.5 to Spring 4.2 and Hibernate 4.2: Autoflush of the objects does not work anymore.
This was our testcase:
// select all not canceled persons
final Query query = currentSession().createQuery(selectSQL);
List<TOPerson> personenListe = query.list();
// canceled first person
TOPerson person = personenListe.get(0);
person.setKnStornoPerson("S"); // canceled Person
// select - select all not canceled persons once again
final Query query2 = currentSession().createQuery(selectSQL2);
List<TOPerson> personenListe2 = query2.list();
Result: The just canceled person still exists in the result set. We expected that query2.list(() performs an autoflush in Hibernate and the result set would not contain the just canceled person. This would be the correct behavior.
We found the cause to be in the OpenSessionInViewInterceptor. Without it the autoflush works correctly.
We used the following configuration:
<util:properties id="hibernateProperties">
<prop key="hibernate.dialect">${env:hibernate.dialect}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">/ehcache.xml</prop>
<prop key="hibernate.cache.use_query_cache">${env:hibernate.useQueryCache}</prop>
<prop key="hibernate.cache.use_second_level_cache">${env:hibernate.useSecondLevelCache}</prop>
<prop key="hibernate.connection.release_mode">after_statement</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory</prop>
</util:properties>
We already considered the information from Bug #14115 in our configuration.
As recommended, we set the property hibernate.transaction.factory_class to the CMTTransactionFactory and added the TransactionManager as a property of SessionFactory. Having done that, the autoflush works fine without the OpenSessionInViewInterceptor.
The autoflush does not work with the OpenSessionInViewInterceptor
Furthermore, we found the method preHandle of OpenSessionInViewInterceptor to be executed right at the beginning of a request. The method preHandle creates a new hibernateSession by calling the method openSession.
This hibernateSession is bount to the thread by the TransactionSynchronizationManager. While creating the hibernateSession, the TransactionCoordinator creates a CMTTransaction-Object. At this point, no active transaction is available, therefore, the join status in CMTTransaction has been set to NOT_JOINED.
Database access within a transaction
According to our architecture, a transaction is being started by AOP in order to execute database access in the persistence tier. This transaction only begins after the execution of preHandle of OpenSessionInViewInterceptor.
The join status of the CMTTransaction that was set in preHandle, stays the same within the actual transaction. Therefore, it looks like the preHandle method corrupts the transactional behavior. Consequently, the autoflush is not being executed later on.
When performing the method query2.list (), we expect the method autoFlushIfRequired to recognize that it is running within a transaction.
Unfortunately, the method isTransactionInProgress returns FALSE! As mentioned before, the cause is the join status to be NOT_JOINED.
protected boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {
errorIfClosed();
if ( ! isTransactionInProgress() ) {
// do not auto-flush while outside a transaction
return false;
}
AutoFlushEvent event = new AutoFlushEvent( querySpaces, this );
for ( AutoFlushEventListener listener : listeners( EventType.AUTO_FLUSH ) ) {
listener.onAutoFlush( event );
}
return event.isFlushRequired();
}
The OpenSessionInViewFilter shows the incorrect behavior as well.
In the test case without the OpenSessionInViewInterceptor the hibernateSession is being created in the currentSession method immediately before the first database access. At this point, a transaction by AOP has already started, therefore the join status of CMTTransaction object is set to JOINED. This leads to the autoflush, which is the expected behavior.
Affects: 4.2 GA
Issue Links:
2 votes, 5 watchers
The text was updated successfully, but these errors were encountered: