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

如何使用MongoItemWriter写入List<T>?自定义实现遇类型转换错误

Spring Batch处理器返回列表时MongoItemWriter的错误解决

我的Spring Batch处理器返回List<Object>,需要将列表中的对象批量写入MongoDB,但自定义MongoItemWriter处理列表时遇到两个错误:

  • 错误1:class org.bson.Document cannot be cast to class java.util.Collection (org.bson.Document is in unnamed module of loader 'app'; java.util.Collection is in module java.base of loader 'bootstrap')
  • 错误2:Attempt to update step execution id=1 with wrong version (1), where current version is 2

相关代码

处理器代码

@Override
public List<PEntity> process(PSEntity item) {
  log.trace("Traitement d'une entrée PSEntity: {}", item);

  List<PL> r = this.r.findRP(item.getP());
  if (r.isEmpty()) {
    return null;
  }
  for (PL r : r) {
    r.setRr(true);
    r.setHr(LocalDateTime.now());
  }
  List<PLEntity> pLEntities =
      r.stream().map(this.pDM::ppDMEntity).toList();
  return pLEntities;
}

自定义RMongoWriter代码

public class RMongoWriter<T> extends MongoItemWriter<List<T>> {
  private MongoOperations template;
  private MongoItemWriter<T> delegate;

  @Override
  public void write(final List<? extends List<T>> lists) throws Exception {
    for (final List<T> list : lists) {
      delegate.write(list);
    }
  }
  @Bean
  public MongoItemWriter<List<PLEntity>> writer(MongoTemplate mongoTemplate,
      BatchConfigurationProperties batchConfigurationProperties) {
    MongoItemWriter<List<PlaqueLueEntity>> writer = new MongoItemWriter<>();
    writer.setTemplate(mongoTemplate);
    writer.setCollection(String.valueOf(CollectionEnum.COLLECTION.PL));
    return writer;
  }
}

BatchConfiguration配置

@Bean
public MongoItemWriter<List<PLEntity>> rWriter() {
  return new RMongoWriter().writer(mongoTemplate, batchConfigurationProperties);
}

错误原因分析

错误1原因

继承MongoItemWriter<List<T>>的做法有误:MongoItemWriter原本设计用于处理单个实体对象,它会尝试把传入的List<T>当作单个Mongo文档序列化,在内部转换为Document时,因List不是Mongo实体类,触发类型转换异常。

错误2原因

这是Spring Batch步骤执行的版本冲突问题,根源是第一个错误导致步骤执行异常,Spring Batch更新步骤状态时,异常引发的重复更新或事务回滚导致版本不匹配。

解决方案

无需继承MongoItemWriter,直接实现ItemWriter<List<T>>,内部用标准MongoItemWriter<T>处理列表中的每个实体:

修改后的自定义Writer

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.data.MongoItemWriter;
import org.springframework.data.mongodb.core.MongoTemplate;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class RMongoWriter<T> implements ItemWriter<List<T>> {
    private final MongoItemWriter<T> delegate;

    public RMongoWriter(MongoItemWriter<T> delegate) {
        this.delegate = delegate;
    }

    @Override
    public void write(List<? extends List<T>> items) throws Exception {
        // 展开所有列表中的实体,统一批量写入
        List<T> allEntities = items.stream()
                .filter(Objects::nonNull)
                .flatMap(List::stream)
                .collect(Collectors.toList());
        if (!allEntities.isEmpty()) {
            delegate.write(allEntities);
        }
    }

    // 单独定义MongoItemWriter的Bean,与自定义Writer解耦
    @Bean
    public MongoItemWriter<PLEntity> mongoPLEntityWriter(MongoTemplate mongoTemplate) {
        MongoItemWriter<PLEntity> writer = new MongoItemWriter<>();
        writer.setTemplate(mongoTemplate);
        writer.setCollection(String.valueOf(CollectionEnum.COLLECTION.PL));
        return writer;
    }
}

修改BatchConfiguration配置

@Bean
public ItemWriter<List<PLEntity>> rWriter(MongoItemWriter<PLEntity> mongoPLEntityWriter) {
    return new RMongoWriter<>(mongoPLEntityWriter);
}

额外注意

  1. 处理器返回null时,Spring Batch会自动跳过该项,需确保此逻辑符合业务预期。
  2. 若需优化写入性能,可调整Spring Batch的chunk大小,配合MongoDB的批量插入机制提升效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:40:25