如何在mybatis的IN子句中使用超过1000个args?

时间:2018-06-11 15:32:13

标签: java oracle orm ibatis spring-mybatis

我使用Oracle数据库和myBatis作为ORM框架,所有查询都在XML映射器文件中。我需要在IN caluse中放置几千个参数,我知道有一个约束,只有1000个参数可以放在那里。我决定寻求解决方案:

WHERE something IN (a1, a2, ..., a1000)
OR something IN (a1001, a1002, ..., a2000)
OR ...

我怎样才能在XML映射器文件中创建它?

<foreach><if>标签等,但我找不到任何可以将上面的SQL代码插入模板的合适内容。

这样的事可以使它发挥作用会很棒:

<some_tag collection="huge_collection" item="huge_collection[1:1000]>

</some_tag>

2 个答案:

答案 0 :(得分:1)

虽然您可以解决IN个参数的数量:

  1. 数以千计的绑定值将导致潜在的兆字节SQL。将此SQL发送到数据库需要很长时间。

  2. 由于SQL解析,效率低下。不仅需要很长时间来解析这个长SQL,而且每个具有不同数量的绑定参数的调用都将被单独解析和计划(参见this article which explains it)。

  3. SQL语句中存在绑定参数的硬限制。您可以重复OR几次以解决IN限制,但是您将在某个时候达到SQL语句限制。

  4. 对于那种类型的查询,通常最好创建一个temporary tables。在查询之前创建它,将所有标识符插入其中并将其与实际查询中的此临时表连接以模拟WHERE语句。

    理想情况下,您可以使用存储过程替换查询。从数据库中提取数万个标识符只是为了在下一个查询中将其传递回数据库,效率很低。

答案 1 :(得分:0)

您可以使用< foreach >标记。这个标签遍历一个集合(集合,列表等),并且可以组装一个大的SQL语句。

您的示例将如下所示:

WHERE something IN (
  <foreach item="i1" collection="list1" separator=",">
    #{i1}
  </foreach>
  )
OR something IN (
  <foreach item="i2" collection="list2" separator=",">
    #{i2}
  </foreach>
  )
OR ...

以下来自MyBatis Manual的示例告诉您更多相关信息:

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>