OpenJpa 中具有大列表的 IN 子句导致语句过于复杂

Posted

技术标签:

【中文标题】OpenJpa 中具有大列表的 IN 子句导致语句过于复杂【英文标题】:IN clause with large list in OpenJpa causing too complex statement 【发布时间】:2014-10-06 06:51:32 【问题描述】:

我必须创建一个命名查询,我需要按一些字段对结果进行分组,并且还使用 IN 子句来限制我的结果。

它看起来像这样

SELECT new MyDTO(e.objID) FROM Entity e WHERE e.objId IN (:listOfIDs) GROUP BY e.attr1, e.attr2 

我正在使用 OpenJPA 和 IBM DB2。在某些情况下,我的 ID 列表可能非常大(>80.000 个 ID),然后生成的 SQL 语句对于 DB2 来说变得过于复杂,因为最终生成的语句会打印出所有 ID,如下所示:

 SELECT new MyDTO(e.objID) FROM Entity e WHERE e.objId IN (1,2,3,4,5,6,7,...) GROUP BY e.attr1, e.attr2 

有什么好的方法来处理这种查询吗?一种可能的解决方法是将 ID 写入临时表中,然后在该表上使用 IN 子句。

【问题讨论】:

JPA 确实是为“少数”记录(仍然可能很多)而设计的,而且集合大小不是。你在做什么,你一次弄乱了这么多记录?您最好将批量加载到要加入的表中(类似于现有答案,但有专门的工具)。 【参考方案1】:

您应该将所有值放在一个表中,并将查询重写为连接。这不仅可以解决您的查询问题,还应该更加高效。

declare global temporary table ids (
   objId int
) with replace on commit preserve rows;

--If this statement is too long, use a couple of insert statements.
insert into session.ids values
    (1,2,3,4,....);

select new mydto(e.objID) 
    from entity e 
    join session.ids i on 
       e.objId = i.objId 
group by e.attr1, e.attr2;

【讨论】:

这可以工作,但我如何访问我的 JPQL 语句中的临时表?我无法直接访问“会话”,因为它未被识别为实体。 所以这似乎是最好的解决方案。我不能使用全局临时表,但我的方法有效。我正在使用“普通”表并根据需要用 id 列表填充它。

以上是关于OpenJpa 中具有大列表的 IN 子句导致语句过于复杂的主要内容,如果未能解决你的问题,请参考以下文章

OpenJPA/MySQL:在 where 子句中使用同一张表时修改表

Informix:IN 子句中的项目数量限制?

我可以使用Java代码在sql语句(Oracle)的IN子句中传递字符串列表吗

从表中选择 WHERE 子句中具有不同 IN 列表的表

如何将 select 语句的 IN 子句中的参数作为具有多个值的参数传递?

JPQL typedquery 中 IN 子句的解析