使用Spring批处理读取文件并写入Map

时间:2016-02-23 07:55:28

标签: java spring hashmap spring-batch

背景

我对Spring批次相当新,并且有以下要求:

  1. 读取最少百万条记录(CSV,管道分隔等)的文件
  2. 将文件中的每一行加载到Map中,其中key作为第一列,value作为域对象/ POJO。
  3. 据我所知,Spring批处理有一种称为面向块的处理,其中一个配置读取器,处理器和编写器来处理由commit-interval控制的一定数量的记录。这可以使用读者的任务执行器或通过分区添加另一层多线程来进一步扩展。

    问题

    如上面第2点所述,我想将我的文件加载到Map中。为了便于讨论,我们假设我实现了以下ItemWriter,它将块聚合成Map。

    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来获取我文件中聚合的记录Map;但是,在ItemWriter中保存这样的Map并不是最好的解决方法。另一个问题是使用ConcurrentHashMap可能会降低性能,但我没有看到任何其他方式可以以线程安全的方式将文件聚合到Map中。

    有没有更好的方法将我的文件聚合到Map中,而不是在我的编写器中使用一个Map并使用ConcurrentHashMap?

2 个答案:

答案 0 :(得分:1)

这或多或少。您可以进行一些小改进,例如将地图放在一个单独的bean中,这样可以让您为编写器bean和地图创建不同的生命周期,并将地图的读者与编写者分离。例如,您可以将地图放在作业范围的bean中,并且仍然将编写器设置为单例,例如。

如果您的工作被划分为多个线程,您只需要一个ConcurrentHashMap(我假设您不希望跨作业共享地图)。

答案 1 :(得分:0)

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

我假设应该将此地图写入文件。可能是一个平面文件(txt)

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

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