January 24, 2012

Hibernate relations and event listeners

1  comments

In my current project I work on a Java EE application with a hibernate backend. The applications supports two databases MSSql and Oracle. The development started with MSSql. One of my tasks was to migrate the application to Oracle. We expected some problems with Spring ACLs which uses SQL instead of OR Mapping. To fix that I just had to write some custom SQL for Oracle.

After handling the ACLs I got transaction problems with oracle, we hadn’t with MSSql. After some tests and research I found out that to fix this I had to add a entityManager.flush(); to the persist and merge method of our entity manager. I was happy to resolved the issue an started our test suite.

Then I run into an exception like this:

Caused by: 
org.hibernate.AssertionFailure: collection [someEntity] was not processed by flush()

I got this exception on our local H2-database on MSSql and Oracle. After some research I found this issue in the hibernate Jira:

HHH-2763: Allow initialization during flush

In the first place I ignored it because the entry was from 2007. After some more research and some tests I found out that our problem looked similar to the issue reported to hibernate. We had relations and we had listeners in the form of PrePersistCallbacks and PreUpdateCallbacks. I couldn’t believe that an issue from 2007 was still not fixed.

My next step was to write a test case to reproduce the error. The test case is very domain specific so I can’t post it here.

I found out that the bug was already fixed in grails. With this knowledge it was easy to came to this solution:

package app.dao;

import org.hibernate.HibernateException;
import org.hibernate.ejb.event.EJB3FlushEventListener;
import org.hibernate.event.EventSource;

/**
 * This file is heavily inspired by the PatchedDefaultFlushEventListener from grails:
 * https://github.com/grails/grails-core/blob/master/grails-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/PatchedDefaultFlushEventListener.java
 * 
 * Patches Hibernate to prevent this issue
 * https://hibernate.onjira.com/browse/HHH-2763
 *
 * TODO: Remove this patch when HHH-2763 is resolved
 * 
 */

public class PatchedFlushListener extends EJB3FlushEventListener {

  private static final long serialVersionUID = -6913148400994182443L;
  
  @Override
  protected void performExecutions( EventSource session ) throws HibernateException {
    session.getPersistenceContext().setFlushing( true );
    try {
      super.performExecutions( session );
    } finally {
      session.getPersistenceContext().setFlushing( false );
    }
  }
}

To make this work in our application I had to add this spring configuration to our applicationContext-datasource.xml:


      
        
        
     	
      

The problem occurred with Hibernate 3.6.7.Final which was the latest stable release by the time I run into it. It should be fixed in Hibernate 4.0.0.Final or later which final release was in december.


Tags

Bug, event listener, Grails, Hibernate, Java, Java EE, JPA, MSSql, Oracle, relations, Spring


You may also like

Leave a Reply

Your email address will not be published. Required fields are marked

Information about Data protection

This site uses Akismet to reduce spam. Learn how your comment data is processed.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}