13

我有一个由应用程序的不同部分加载的 Hibernate 域对象。有时延迟加载每个关联是有利的,而其他关联则最好在一个连接中加载整个事物。作为一个有希望的妥协,我发现:

使用批量获取,如果访问一个代理,Hibernate 可以加载多个未初始化的代理。批量抓取是对惰性选择抓取策略的优化。

hibernate.default_batch_fetch_size

使用批量获取,如果访问一个代理,Hibernate 可以加载多个未初始化的代理。批量抓取是对惰性选择抓取策略的优化。

我还看到:

hibernate.jdbc.fetch_size

非零值确定 JDBC 提取大小(调用 Statement.setFetchSize())。

那么 Hibernate 是否足够聪明,可以在批量获取时查看二级缓存?即为对关联的初始调用进行一次获取,然后下一个 X 调用命中缓存?这样我就可以进行我想要的延迟加载,但也可以经常访问缓存以进行更多类似批量的事务。

如果集合的全部内容已经包含在缓存中,它还会在访问集合时执行获取查询吗?

谢谢。

4

1 回答 1

6

我今天做了很多研究,并能够找到对我自己问题的回应。我正在查看 Hibernate 代码,流程如下所示:

集合是否已初始化?

  • 不?做一个batch fetch(batch-fetch得到的item放到缓存中)
  • 是的?在缓存中查找特定项目,如果不存在,请进行批量获取。

因此,如果在缓存中找到您要查找的集合中的项目,则不会发生批量提取。如果在二级缓存中未找到该项目,则进行批量获取,但无论批量项目是否在缓存中,它都会获取批量项目。


----- 示例 1 -----

好:

(一个集合中的三个项目 - 批量大小为 3)第一个:

  • collection.getItem(0) - 无缓存 | 批量获取 3 个项目
  • collection.getItem(1) - 通过批量获取加载
  • collection.getItem(2) - 通过批量获取加载

现在,在其他地方,稍后的时间:

  • collection.getItem(0) - 缓存命中
  • collection.getItem(1) - 缓存命中
  • collection.getItem(2) - 缓存命中

----- 示例 2 -----

坏处:

(一个集合中的三个项目 - 批量大小为 3)

在这种情况下,索引 0 处的项目已从缓存中删除,因为可能缓存已满并且该项目已被删除,或者该项目已过时或空闲。

  • collection.getItem(0) - 不在缓存中,批次 3 也是如此(选择 * where id in (?, ?, ?))
  • collection.getItem(1) - 已经在缓存中(无论如何都被批量获取替换)
  • collection.getItem(2) - 已经在缓存中(无论如何都被批量获取替换)

所以这里的权衡是,由于批处理,您将有更少的 SQL 调用,但您会更频繁地错过缓存。在进入数据库之前,有一张票可以在二级缓存中查看批处理。

http://opensource.atlassian.com/projects/hibernate/browse/HHH-1775

投票!

于 2009-08-26T00:33:38.860 回答