myBATIS foreach 达到 1000 的限制

Art*_*are 2 java oracle mybatis

是 myBATIS 在他们自己的foreach.

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>
Run Code Online (Sandbox Code Playgroud)

但是,如果list包含超过 1000 个项目并且您使用的是 Oracle DB,则会出现以下异常:

java.sql.SQLSyntaxErrorException: ORA-01795: maximum number of expressions in a list is 1000
Run Code Online (Sandbox Code Playgroud)

我能做些什么来解决这个问题,使其适用于 1000 多个元素?

Art*_*are 6

我不确定这是否是最优雅的解决方案,但这是我所做的:

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <trim suffixOverrides=" OR ID IN ()">
      <foreach item="item" index="index" collection="list"
               open="(" close=")">
          <if test="index != 0">
              <choose>
                  <when test="index % 1000 == 999">) OR ID IN (</when>
                  <otherwise>,</otherwise>
              </choose>
          </if>
          #{item}
      </foreach>
  </trim>
</select>
Run Code Online (Sandbox Code Playgroud)

解释

让我们从foreach. 我们想用(and包围它)。我们希望在大多数元素之间使用逗号,除了我们希望停止列表的每千个元素和OR另一个元素。这就是choose, when,otherwise构造处理的内容。除了我们不想要第一个元素之前的任何一个,因此里面的if那个choose。最后,foreach以实际#{item}插入结束。

外部trim只是这样,例如,如果我们恰好有 1000 个元素,我们不会OR ID IN ()以无效的 ( (),具体来说,是无效部分。这是 SQL 中的语法错误,而不是我希望的空列表将是。)