I am using Hibernate 4.2, and i have a parent entity which contains a collections of child entities (One-To-Many ,fetch type is LAZY and annotated with @BatchSize(size=100))
.
If i query and load few parent entities and call access that collection which contains child object, hibernate uses the @BatchSize
as the expected.
But if i call session, flush and then do the same thing, it initializes collection only for that particular parent entity.
Is it the Hibernate expected behavior?
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
I am going to answer my own question because i think this would help others. I think this is the Hibernate behavior even though it is not mentioned in any document. when we call Session.flush , it calls to the Flushing event listener and and i found this code in 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
So if I get your question correctly you do the following (pseudo code)
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 to me, but if you do a session.commit or session.clear instead of the flush, it would be expected, because now b is no longer part of the session and therefor it is no candidate for batch fetching.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With