【问题标题】:JPA/Hibernate seems to convert a query with an in clause into multiple queries with = clausesJPA/Hibernate 似乎将带有 in 子句的查询转换为带有 = 子句的多个查询
【发布时间】:2019-08-23 23:47:19
【问题描述】:

我们实施的一个解决方案是为了在合理的时间内收集大量重型对象并且没有内存溢出(我说的是具有多个 fetchType.eager 关系的对象,以及本身具有急切获取关系的实体),是首先选择那些对象的id,然后根据这些id选择对象本身。

到了优化我们代码的时候,我们注意到(使用hibernate.show_sql=true)我们用来收集这些对象的查询(select a from A a where a.id in :ids)被JPA/Hibernate 翻译成数千个select a from ...endless join list... where a.id = ?形式的查询

问题如下:

为什么 JPA/Hibernate 将我们带有“in”子句的初始查询转换成这么多带有“=”子句的查询。不是效率低吗?如果是这样,有没有办法防止这种情况发生?

以下是我们的代码中调用查询的方式:

    Query q = this.getContext().createQuery("select a from A a where a.id in :ids");
    q.setParameter("ids", idList);
    return (List<A>) q.getResultList();

【问题讨论】:

标签: java oracle performance jpa


【解决方案1】:

虽然我仍然无法解释为什么会为 in 子句中提供的每个 ID 生成查询(在我的原始问题中提供),但我在此博客 (https://thoughts-on-java.org/fetch-multiple-entities-id-hibernate/) 上找到了解决此问题的方法。 解决方案在于使用 Hibernate 的会话 API,如下所示:

//get session object from entity manager
Session session = em.unwrap(Session.

MultiIdentifierLoadAccess<A> multiLoadAccess = session.byMultipleIds(A.class);
List<A> aObjects= multiLoadAccess.withBatchSize(1000).multiLoad(idList);
return aObjects;

【讨论】:

    【解决方案2】:

    您好,您应该使用setParameterList 而不是setParameter。 如果你想获得完整的实体对象,也不需要在休眠中使用select

     Query q = this.getContext().createQuery("from A a where a.id in (:ids)");
    q.setParameterList("ids", idList);
    return (List<A>) q.getResultList();
    

    【讨论】:

    • 当我最初发布我的问题时,查询类型存在混淆。这是一个基本的 jpa 查询,因此要使用 setParameter。感谢您提供有关选择的提示,但是我不知道
    【解决方案3】:

    如果您的 idList 超过 1000 个元素,您可能会遇到此 Oracle 特定的去优化 https://hibernate.atlassian.net/browse/HHH-9299

    解决此问题的一种方法是将idList 分成多个块,为每个块执行查询并连接结果。

    【讨论】:

    • 正好是 1000 个元素。我考虑到了这个限制,并在执行查询之前对我的 id 列表进行了分区。如果我有一个包含超过 1000 个元素的 idList,就会发生 ORA 异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    • 2021-02-19
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多