<foreach> 标签in()的数据不能超过1000个的问题

文章讲述了在使用MyBatis的foreach标签处理大数据量集合时,由于Oracle对IN语句表达式数量有限制(1000个),会出现错误。提出了两种解决方案:一是利用OR每1000个元素添加一个OR条件,二是使用trim标签配合suffixOverrides属性来动态拼接SQL,避免超过限制。这两种方法都旨在优化SQL,使其能正确执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

foreach元素的属性主要有 collection、item、index、open、separator、close


collection : foreach循环的对象
item : 集合中每一个元素或者该集合的对象,支持对象点属性的方式获取属性#{obj.filed} 或#{value}
index :循环的下标,从0开始 
open : 表示以什么开始 
separator : 每次进行迭代之间以什么符号作为分隔符 
close :表示以什么结束

 

 trim 标签四个属性和其作用

prefix : 添加前缀
prefixOverrides : 删除前缀
suffix : 添加后缀
suffixOverrides : 删除后缀

问题复现:

  select distinct  MV_NO "mvnoMark"   from table_user
        where  mv_no=#{mvno}
        <if test="userIdList!=null and userIdList.size()>0">
            and user_no in
            <foreach collection="userIdList" item="userId" open="(" close=")" separator=",">
                #{userId,jdbcType=VARCHAR}
            </foreach>
        </if>
        <if test="userIdList.size()==0">
            and user_no =''
        </if>

错误原因:

        当<foreach>标签内的数量超过1000个时会提示一下报错:

java.sql.SQLException: ORA-01795: maximum number of expressions in a list is 1000

解决方案:

一、利用or每1000条添加一个or

  select distinct  MV_NO "mvnoMark" from table_user
        where  mv_no=#{mvno}
        <if test="userIdList!=null and userIdList.size()>0">
            and user_no in
<foreach collection="userIdList" item="userId" index="index" open="(" close=")" separator=",">
            <if test="(index % 1000) == 999"> NULL) OR  user_no in(</if>  #{userId,jdbcType=VARCHAR}
        </foreach>
        </if>
        <if test="userIdList.size()==0">
            and user_no =''
        </if>

分析:

        其实也是用 or 进行sql拼接

SQL执行的样子:

user_no in('......','999',NULL ) OR user_noD in('1000',..... NULL) OR user_no in('.....')

二、拼接OR ID IN ()

  select distinct  MV_NO "mvnoMark" from table_user
        where mv_no=#{mvno}
        <if test="userIdList!=null and userIdList.size()>0">
            and user_no in
            <trim suffixOverrides=" OR user_no in ()">
            <foreach collection="userIdList" item="userId" index="index" open="(" close=")" >
                <if test="index != 0">
                    <choose>
                        <when test="index % 1000 == 999">)  OR user_no in (</when>
                        <otherwise>,</otherwise>
                    </choose>
                </if>
                #{userId,jdbcType=VARCHAR}
            </foreach>
            </trim>
        </if>

分析:

<trim>标签suffixOverrides:去掉后缀匹配上的东西,本例中后缀如果是 or user_no in()与suffixOverrides的属性值刚好匹配,则去掉 or user_no in()
 
index 集合迭代的位置从0开始,为何需要<if test="index != 0">?如果没有,则sql是 user_no in (,1,2..)会多一个逗号
 
没有1000条数据的拼接SQL为:user_no (1,2..999) 
超过1000条的数据拼接SQL为:user_no (1,2..999) oruser_no(1000,1001...1999) ...

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值