【问题标题】:Hibernate @BatchSize doesn't work as expected after session.flush在 session.flush 之后休眠 @BatchSize 无法按预期工作
【发布时间】:2015-07-31 10:56:47
【问题描述】:

我使用的是 Hibernate 4.2,并且我有一个父实体,其中包含一组子实体(一对多,获取类型是 LAZY 并带有 @BatchSize(size=100)) 注释。

如果我查询并加载几个父实体并调用访问包含子对象的集合,休眠将使用 @BatchSize 作为预期。 但是如果我调用 session、flush 然后做同样的事情,它只会为那个特定的父实体初始化集合。

这是 Hibernate 的预期行为吗?

编辑:示例

列出父母 = criteria.list() parents.get(0).getXs().get(0) // 触发加载所有父母的 Xs

对比

列出父母 = criteria.list() session.flush() parents.get(0).getXs().get(0) // 触发仅加载第一个父级的 Xs

【问题讨论】:

  • 这与Session.flush无关。你的意思是Session.clear
  • 不,我确定我使用了会话刷新,我已经对此进行了测试。我知道如果我不调用 session.flush,那么我的问题就会得到解决。但我想知道这背后的理论。
  • 你可以尝试使用HQL加载父母吗?

标签: java hibernate


【解决方案1】:

我将回答我自己的问题,因为我认为这会对其他人有所帮助。 我认为这是 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

【讨论】:

  • 我在那个上面花了 2 天时间。除了我的刷新是由我的 ejb 边界隐式调用的。感谢您的研究,
【解决方案2】:

因此,如果我正确地回答了您的问题,请执行以下操作(伪代码)

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

对比

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

这对我来说很奇怪,但是如果您执行 session.commit 或 session.clear 而不是刷新,这是可以预料的,因为现在 b 不再是会话的一部分,因此它不是批量获取的候选者.

【讨论】:

  • 是的,但更准确地说,我使用了 criteria.list ,这意味着加载 a 和 b 是在一行中,然后如果我执行 session.flush 那么批量大小不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
  • 2011-08-06
  • 2021-10-13
  • 2014-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多