如何在spring批处理中使用itemWriter编写子记录

时间:2013-08-27 09:35:27

标签: java spring-batch

我的情况:

我有一个A类,我在readerItem中从db读取。然后我需要处理这个类A并创建我在itemProcessor中执行的类B.最后我将这个类B保存到itemWriter中的db。

问题:在处理过程中,我还需要创建具有B类外键的C类(大约1 mil记录)并保存此C类。我应该怎么做。

我不能这样做: 因为正如我所写,我有大约1密耳的记录,我应该在内存中存储大约2GB的空间。那我该怎么解决这个问题。

public class BWriter extends BaseItemWriter<B> {

    public void write(List<? extends B> data) throws Exception {
        logger.info("Start writing: " + data);
        for (B item : data) {
            myCustomDao.saveB(item);
            for (C itemC : item.getC()) {
                itemC.setB(item);
                myCustomDao.saveC(itemC);
            }
        }
    }
}

更新:

可能的解决方案,不包括我想要的弹簧批次:

    List<C> cList = new ArrayList<C>();
    int i = 0;
    String line;
    while ((line = reader.readLine()) != null) {
        String[] data = line.split(";");
        if (data.length > 1 && !StringUtils.isBlank(data[1])) {
            C cItem = new C();
            cItem.set(...);
            cList.add(i, cItem);
            if (++i >= 1000) {
                myCustomDao.save(cList);
                cList = new ArrayList<C>();
                i = 0;
            }
        }
    }
  if (!cList.isEmpty())
                myCustomDao.save(cList);

1 个答案:

答案 0 :(得分:0)

如果将commit-interval减少到一个小值而不是一个选项,因为一个B元素可以有最多1mil的C对象,你可以这样做:

将A类处理到B类,而不在已处理的B对象中创建C对象;
BWriter中附加一个ItemWriteListener<B>.afterWrite(),您可以在其中创建/保存C对象(与收听者中收到的List<B>相关),这样您的内存消耗就会很低,但您可以保证在交易边界工作。

如果问题是由于使用Hibernate而不是普通JDBC,您可以考虑手动使用无状态会话或flush()/clear()会话; 1mil的数据库记录不是很大的数字 不幸的是,当您拥有大量数据时,ORM不是最佳选择。

我的2美分,我对你来说是一个很新的批次。