[英]JPA/Hibernate seems to convert a query with an in clause into multiple queries with = clauses
我们实现的解决方案是为了在合理的时间内收集大量重物并且没有内存溢出(我说的是具有多个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();
您好,您应该使用setParameterList而不是setParameter
。 如果你想获得完整的实体对象,也不需要在hibernate中使用select
。
Query q = this.getContext().createQuery("from A a where a.id in (:ids)");
q.setParameterList("ids", idList);
return (List<A>) q.getResultList();
如果你的idList
超过1000个元素,你可能会遇到这个特定于Oracle的去优化https://hibernate.atlassian.net/browse/HHH-9299 。
解决此问题的一种方法是将idList
分解为多个块,对每个块执行查询并连接结果。
虽然我仍然无法解释为什么为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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.