You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

并行流操作引发MyBatis foreach生成异常SQL问题排查

并行流操作HashSet导致生成不完整SQL的原因及修复
  • 问题根源:HashSet是非线程安全的容器,在parallelStream().forEach()中多线程并发调用add()方法时,会造成内部数据结构损坏(比如哈希表冲突、size计数异常)。哪怕原list非空,最终的ids集合可能出现两种情况:要么元素全部丢失导致集合为空,要么集合的size显示非空但实际没有可遍历的元素。后者会绕过ObjectUtils.isEmpty(ids)的判断,传给MyBatis后,<foreach>遍历不到元素,就生成了select name from user where id in这种不完整的SQL。

  • 修复方案:并行流中必须使用线程安全的方式收集结果,用Collectors.toSet()替代手动操作HashSet:

public List<String> queryByIds() {
    Set<Long> ids = list.parallelStream()
        .map(obj -> obj.id)
        .collect(Collectors.toSet());

    if (ObjectUtils.isEmpty(ids)){
        return Collections.emptyList();
    }
    return mapper.queryByIds(ids);
}

Collectors.toSet()在并行流场景下会自动使用线程安全的收集容器,避免并发修改导致的数据异常,保证ids集合能正确收集所有元素。

  • 补充说明:原代码里ids.add(obj.id)末尾缺了分号,这是语法错误,应该是输入时的笔误。核心问题还是非线程安全容器在并行流中的误用。

内容的提问来源于stack exchange,提问作者senz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:52:33