在Oracle IN Operator中使用JPA和100​​0 ID

时间:2018-09-17 08:34:20

标签: java oracle hibernate jpa oracle11g

我使用NamedNativeQuery删除行,就像这样:

DELETE from FAKTOR
 where ID IN (
   select fa.ID
   from FAKTOR fa
     left join FAKTOR_REASON fars
       on fa.FARS_ID = fars.ID
   where fars.ID = 63
         and fa.USER_ID in (:userIds))

但是我如何在Oracle的IN Operator中使用1000个以上的userIds提示呢?

P.S::我正在寻找一种解决方案,一次提交即可处理;

2 个答案:

答案 0 :(得分:5)

解决IN限制是效率低下的,并且JPA并非总是适合该工作的工具。请考虑以下内容:

  1. 数千个绑定值将导致潜在的兆字节SQL。将此SQL发送到数据库将花费很长时间。数据库可能比根据Tom's answer to "Limit and conversion very long IN list: WHERE x IN ( ,,, ...)" question执行SQL文本花费的时间更长。

  2. 由于SQL解析,效率低下。

  3. 不仅解析此长的SQL需要花费很长时间,而且每次调用都有不同数量的绑定参数,这些参数将分别解析和计划(请参阅this article which explains it)。

  4. SQL语句中对绑定参数有硬限制。您可以重复执行OR几次,以达到IN的限制,但有时会达到SQL语句的限制。

对于这些类型的查询,通常最好创建temporary tables。在查询之前创建一个,将所有标识符插入其中,并将其与查询中的实体表连接起来以模拟IN条件。

理想情况下,您可以用存储过程替换JPA,尤其是当您从数据库中提取成千上万个标识符只是为了在下一个查询中将它们传递回数据库时。

答案 1 :(得分:0)

我建议在Java代码中对dist列表进行分区的解决方案。 Google Guava具有userIds方法,您可以在其中执行以下操作:

Lists.partition

然后,您可以将List<List<Integer>> userIdsParts = Lists.partition(userIds, 1000); 的运算符的每个部分与in连接起来:

OR

我建议使用查询构建器(例如QueryDSL)来执行此逻辑,因为您通常不知道where ... and (fa.USER_ID in (:userIdsPart1) or fa.USER_ID in (:userIdsPart2) or ...) ... 的大小,那么您不知道列表将包含多少部分。 / p>

希望我能帮助您! ;)