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

Spring Boot新增分类与多商品时触发ConcurrentModificationException问题排查

问题分析与修复方案

问题原因

你遇到的ConcurrentModificationException是因为在遍历Category的products列表时,同时修改了这个列表的结构:

  • 控制器中通过products.forEach(item -> c.add(item))遍历列表
  • c.add(item)方法内部执行了products.add(item),相当于在遍历过程中往同一个列表里添加元素
  • ArrayList的forEach基于迭代器实现,迭代期间修改集合结构(添加/删除元素)会触发该异常,因为迭代器会校验集合的修改次数是否和预期一致。

修复方案

方案一:直接设置双向关联(推荐)

原代码中@RequestBody传递的Category已经包含了要新增的products列表,不需要再调用add方法重复添加元素,只需要给每个Product设置对应的Category关联即可:

@RequestMapping(method = RequestMethod.POST)
public void addcategory(@RequestBody Category c) throws IOException {
    List<Product> products = c.getProducts();
    if (products != null) {
        // 仅设置Product的category关联,无需重复添加到列表
        products.forEach(item -> item.setCategory(c));
    }
    categorieRepository.save(c);
}

由于你的@OneToMany注解配置了cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},保存Category时会自动级联保存关联的Product对象。

方案二:遍历列表副本(不推荐,仅作原理演示)

如果一定要保留add方法的调用,需要遍历原列表的副本,避免遍历过程中修改原列表:

@RequestMapping(method = RequestMethod.POST)
public void addcategory(@RequestBody Category c) throws IOException {
    // 复制原列表为新集合,遍历副本时修改原列表不会触发异常
    List<Product> products = new ArrayList<>(c.getProducts());
    products.forEach(item -> c.add(item));
    categorieRepository.save(c);
}

注意:这个方案会导致products列表中出现重复的Product对象,因此不推荐使用。

额外优化建议

可以在Category的add方法中添加重复校验,避免重复添加同一个Product:

public void add(Product item) {
    if (item != null && products != null && !products.contains(item)) {
        products.add(item);
        item.setCategory(this);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:31:06