我正在使用Hibernate 4.2,我有一个包含子实体集合的父实体(一对多,获取类型为LAZY,注释为@BatchSize(size=100))
。
如果我查询并加载少数父实体并调用访问包含子对象的集合,则hibernate使用@BatchSize
作为预期。
但是,如果我调用session,flush然后执行相同的操作,它只为该特定父实体初始化集合。
这是Hibernate预期的行为吗?
编辑:示例
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
答案 0 :(得分:3)
我将回答我自己的问题,因为我认为这会有助于其他人。 我认为这是Hibernate行为,即使它没有在任何文档中提到过。 当我们调用Session.flush时,它调用Flushing事件监听器,并且我在AbstractFlushingEventListenrner类中找到了这段代码
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 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();
因此,最后一行清除当前上下文的BatchFetchQueue
答案 1 :(得分:1)
因此,如果我正确地提出您的问题,请执行以下操作(伪代码)
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
这对我来说很奇怪,但是如果你做session.com或session.clear而不是flush,那就是预期的,因为现在b不再是会话的一部分,因此它不是批量提取的候选者