java - Hibernate可以批量数据库查询二级缓存中集合未命中的情况吗?

标签 java hibernate

对于 Hibernate 3.5.4,假设我有一个如下定义的 hibernate 实体:

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Team {

    @Id
    protected Long id;
    protected List<Player> players;

    @OneToMany(targetEntity = Player.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @NotFound(action= NotFoundAction.IGNORE)
    @org.hibernate.annotations.BatchSize(size = 50)

    public List<Player> getPlayers() {
        return this.players;
    }

    public List<Player> setPlayers(List<Player> players) {
        this.players = players;
    }

    // More stuff

}

然后我按照您的预期定义了一个 Player 实体。从逻辑上讲,这会创建三个二级对象缓存:

  • 团队
  • 团队成员
  • 玩家

我发现,如果查询的团队的 Team.players 缓存被禁用或为空,Hibernate 会向数据库发出批量请求,在该数据库中通过一个查询检索团队的所有玩家(查找player.player.player)。 team_id = 团队 ID)。但是,如果 Team.players 缓存包含 Team 和玩家列表之间的缓存关联,并且 Player 缓存中不存在这些 Player 对象,则 Hibernate 将一次一个检索每个 Player 对象通过 Player.Id 和单独的数据库查询。 有没有办法让Hibernate批量检索这些集合字段对象缓存未命中的情况?

我已尝试设置以下参数的值,但它们似乎不会影响此行为:

  • default_batch_fetch_size
  • jdbc.batch_versioned_data
  • jdbc.batch_size
  • jdbc.fetch_size

我也尝试过 EAGER 抓取而不是 LAZY。

2008 年的这篇 hibernate 论坛帖子提到了这个问题 ( https://forum.hibernate.org/viewtopic.php?t=983649 ),但我还没有找到任何解决方案。感谢您的帮助!

最佳答案

是的,你可以做到。

建立一个Collection<Long> (假设这是您的玩家 ID 类型)。迭代球队的球员列表,使用 Hibernate.isInitialized(player) 检查球员对象。如果为 false,则将 id 添加到集合中。这是假设你的 @Id位于玩家的 id getter 上(而不是字段),因此您可以从玩家代理获取 id,而无需访问数据库。

如果您使用的是 Java EE 6:而不是 Hibernate.isInitialized(player) ,尝试em.getEntityManagerFactory().getPersistenceUnitUtil().isLoaded(player) 。对于容器独立性来说这是首选。

获得列表后,检查它是否不为空。如果不为空,则运行查询:

SELECT p
JOIN Player p
WHERE p.id IN (:idList)

设置 idList参数与您的 Collection<Long>

只需运行 query.getResultList() ;不必费心将查询结果存储在任何地方。这将具体化之前从团队集合中加载的所有代理。

关于java - Hibernate可以批量数据库查询二级缓存中集合未命中的情况吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21145605/

相关文章:

java - 如何在不更改注释的情况下禁用 Hibernate 中某些特定实体的二级缓存

java - 通过 Java 代码访问 Kerberized 服务时是否需要 kinit?

java - 如何在方法中使用其他类的整数?

java - 碧 Jade 报告 : Creating a Watermark with the Background Band

java - getOwnerType 方法的示例

java - 用于集合映射的 JVM Pact Dsl 主体

java - 使用 Maven 的 SpringMVC 和 Hibernate

Java数据结构与Hibernate一起使用来存储未知数量的参数?

spring - Liquibase Hibernate 不一致

java - 在 @PersistenceContext 中设置 unitName 的 Spring Hibernate 配置