简体   繁体   English

在session.flush之后,Hibernate @BatchSize无法按预期工作

[英]Hibernate @BatchSize doesn't work as expected after session.flush

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)) . 我正在使用Hibernate 4.2,并且我有一个包含子实体集合的父实体(一对多,获取类型为LAZY,并使用@BatchSize(size=100))注释@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. 如果我查询并加载几个父实体并调用访问包含子对象的集合,则hibernate使用@BatchSize作为预期。 But if i call session, flush and then do the same thing, it initializes collection only for that particular parent entity. 但是如果我调用session,flush然后执行相同的操作,它只为该特定父实体初始化集合。

Is it the Hibernate expected behavior? 这是Hibernate预期的行为吗?

Edit: sample 编辑:样本

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

vs 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. 我认为这是Hibernate行为,即使它没有在任何文档中提到过。 when we call Session.flush , it calls to the Flushing event listener and and i found this code in AbstractFlushingEventListenrner class 当我们调用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();

So this last line clears the BatchFetchQueue for the current context 因此,最后一行清除当前上下文的BatchFetchQueue

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 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. 这对我来说很奇怪,但是如果你做session.com或session.clear而不是flush,那就可以了,因为现在b不再是会话的一部分,因此它不是批量提取的候选者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM