Hibernate @BatchSize not working properly after session.flush

I use Hibernate 4.2, and I have a parent object that contains collections of child objects (one-to-many, the LAZY fetch type and annotated using @BatchSize(size=100)) .

If I request and load multiple parent objects and call access to this collection containing the child, hibernate uses @BatchSize as expected. But if I call the session, flush and then do the same thing, it initializes the collection only for that particular parent.

Is this the expected behavior of Hibernate?

Edit: sample

  List parents = criteria.list ()
     parents.get (0) .getXs (). get (0) // triggers loading Xs of all parents 
    

vs

  List parents = criteria.list ()
     session.flush ()
     parents.get (0) .getXs (). get (0) // triggers loading Xs of only the first parent
    
+6
source share
2 answers

I am going to answer my question because I think this will help others. I think this is Hibernate behavior, although it is not mentioned in any document. when we call Session.flush, it calls the Flushing event listener, and I found this code in the AbstractFlushingEventListenrner class

 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Post-flushing section // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * 1. Recreate the collection key -> collection map * 2. rebuild the collection entries * 3. call Interceptor.postFlush() */ protected void postFlush(SessionImplementor session) throws HibernateException { LOG.trace( "Post flush" ); final PersistenceContext persistenceContext = session.getPersistenceContext(); persistenceContext.getCollectionsByKey().clear(); // the database has changed now, so the subselect results need to be invalidated // the batch fetching queues should also be cleared - especially the collection batch fetching one persistenceContext.getBatchFetchQueue().clear(); 

So this last line clears the BatchFetchQueue for the current context

+2
source

So, if I ask the question correctly, you will do the following (pseudocode)

 a = loadSomeEntity b = loadSomeEntity a.getXs.get(0) // triggers loading of Xs for a and b 

vs

 b = loadSomeEntity session.flush a = loadSomeEntity a.getXs.get(0) // triggers loading only of Xs for a 

This is strange for me, but if you do session.commit or session.clear instead of a flush, you would expect it because now b is no longer part of the session, and therefore it is not a candidate for batch selection.

+1
source

All Articles