有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用Spring批处理读取文件并写入映射

背景

我是Spring batch的新手,有以下要求:

  1. 读取至少有一百万条记录(CSV、管道分隔等)的文件
  2. 将文件中的每一行加载到一个映射中,其中key作为第一列,value作为域对象/POJO

我知道SpringBatch有一种称为面向块的处理的方法,在这种方法中,可以配置读卡器、处理器和写入器来处理由提交间隔控制的一定数量的记录。可以使用读卡器的任务执行器或通过分区添加另一层多线程来进一步扩展

问题

如上文第2点所述,我想将文件加载到地图中。为了便于讨论,假设我实现了以下ItemWriter,它将块聚合到一个映射中

public class MapItemWriter implements ItemWriter<SomePOJO> {

    private Map<String, SomePOJO> somePojoMap; 

    public MapItemWriter() {
        System.out.println("Writer created ");
        somePojoMap= new ConcurrentHashMap<String, SomePOJO>();
    }

    public void write(List<? extends SomePOJO> item) throws Exception {
        if (item != null && item.size() > 0) {
            for (SomePOJO data : item) {
                String uniqueId = data.Id();
                somePojoMap.put(uniqueId, data);
             }
        }
    }

    public Map<String, SomePojo> getSomePojoMap() {
        return somePojoMap;
    }
}

因为我可以访问ItemWriter bean,所以我可以稍后调用getSomePojoMap来获取文件中记录的聚合映射;然而,在ItemWriter中持有这样的地图并不是最好的方式。另一个问题是使用ConcurrentHashMap可能会降低性能,但我看不到任何其他方法可以以线程安全的方式将文件聚合到映射中

有没有更好的方法将文件聚合到映射中,而不是将映射保存在writer中并使用ConcurrentHashMap


共 (2) 个答案

  1. # 1 楼答案

    差不多是这样。您可以做一些小的改进,比如将地图放在一个单独的bean中,这将允许编写器bean和地图拥有不同的生命周期,还可以将地图的读者与编写器分离。例如,您可以将映射放在一个作业范围的bean中,而编写器仍然是一个单例

    如果您的作业被划分为多个线程,则只需要一个ConcurrentHashMap(我假设您不希望在作业之间共享映射)

  2. # 2 楼答案

    为什么不使用文件项编写器

    我认为这张地图应该被写入一个文件。可能是一个平面文件(txt)

    如果是这种情况,尝试使用FlatFileItemWriter。如果需要将这些数据写入xml文件,可以使用StaxEventItemWriter

    即使您不需要将数据写入文件(在批处理结束时只需要映射)。我认为将数据写入文件,然后从文件中读取整个地图会“更便宜”。在作业范围内保存映射意味着该对象将在每个块的db中持久化,并从每个块的db中检索,这是一个非常昂贵的操作