Spring batch Spring批处理多行记录项编写器,每个记录的行数可变

Spring batch Spring批处理多行记录项编写器,每个记录的行数可变,spring-batch,Spring Batch,我有以下要求,但无法决定采取何种方法: 我需要将数据写入固定格式的输出文件,其中每条记录跨越多行,如下所示: 000120992599999990000000000000009291100000000000000000000000010000 000000000000000000000006050052570009700000050000990494920000111100 ABCDE:WXYZ

我有以下要求,但无法决定采取何种方法:

我需要将数据写入固定格式的输出文件,其中每条记录跨越多行,如下所示:

000120992599999990000000000000009291100000000000000000000000010000
000000000000000000000006050052570009700000050000990494920000111100
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
000000000000000000000006050052730005700001100000090494920000221200
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
000000000000000000000006050113110009700000000000000494920000311100
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
000012099259999999000000000000000929110000000000000000000000001000
这是上面示例中的一条记录:

000000000000000000000006050052570009700000050000990494920000111100
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
第一行和最后一行分别是页眉和页脚。 每条记录的第一行包含若干详细信息。 第二行有一些其他细节与空间

我有一个很长的描述字段,我需要将其分为56个字符的部分,并将记录的第3行加在后面

所以在一些记录中,这可能只是一行,而在一些记录中,它也可能是三行

我需要关于如何在上述场景中设计itemwriter的指导


Nik

官方中有一个多行记录编写器示例,搜索
multiline.xml
multilitradeitemwriter

这基本上是通常的委托原则,您只需要一个适当的域对象,其中包含1..n个中间行的列表

    public class MultiLineTradeItemWriter implements ItemWriter<Trade>, ItemStream {

    private FlatFileItemWriter<String> delegate;

    public void write(List<? extends Trade> items) throws Exception {
                List<String> lines = new ArrayList<String>();
              for (Trade t : items) {
              lines.add("BEGIN");
              lines.add("INFO," + t.getIsin() + "," + t.getCustomer());
              lines.add("AMNT," + t.getQuantity() + "," + t.getPrice());
              lines.add("END");
            }
            this.delegate.write(lines);
     }
    }
public类multilitradeitemwriter实现ItemWriter、ItemStream{
私有FlatFileItemWriter委托;

public void write(List您可以在CustomExtractor中执行此操作

例如:

     public Object[] extract(T item) {
        List<Object> values = new ArrayList<Object>();

        BeanWrapper bw = new BeanWrapperImpl(item);
        for (String propertyName : this.names) {
            values.add( bw.getPropertyValue(propertyName) + "\r\n");
        }
        return values.toArray();
    }
公共对象[]提取(T项){
列表值=新的ArrayList();
BeanRapper bw=新的BeanRapperImpl(项目);
for(字符串属性名称:this.names){
add(bw.getPropertyValue(propertyName)+“\r\n”);
}
返回值。toArray();
}

我在将多行写入数据库时遇到类似的问题。因为作业步骤将创建项目列表,因此如何将列表从处理器返回给编写器?这将创建列表列表,而编写器中的doWrite方法未设置为处理该情况

我正在使用1.2.0 spring boot starter父级(它为我提供了spring core 4.1.3)和hibernate(4.3.7),在我的情况下,我有“应收款”,并且对于从csv文件中读取的每1个应收款,我可能需要更新或将许多应收款插入到我的表中。我还使用HibernateItemWriter

我的解决方案是扩展HibernateItemWriter。sessionFactory字段是私有的,因此我通过构造函数传递它,并使用setter(容纳现有代码)。因此,我的原始代码(对于单个“可接收”代码可以正常工作)最初看起来如下:

    @Bean
    public ItemWriter<Receivable> recivableWriter() {
        HibernateItemWriter<Receivable> hibernateItemWriter = new HibernateItemWriter<Receivable>(){{ setSessionFactory(sessionFactory); }};
        return hibernateItemWriter;
    }
@Bean
public ItemWriter recivableWriter(){
HibernateItemWriter HibernateItemWriter=新的HibernateItemWriter(){{{setSessionFactory(sessionFactory);};
返回hibernateItemWriter;
}
扩展HibernateItemWriter并修改处理器以返回列表后,我的代码更改为:

    @Bean
    public ItemWriter<List<Receivable>> receivableWriter() {
        HibernateListItemWriter<List<Receivable>> hibernateItemWriter = new HibernateListItemWriter<List<Receivable>>(this.sessionFactory){{ setSessionFactory(sessionFactory); }};
        return hibernateItemWriter;
    }
@Bean
公共项目编写器receivableWriter(){
HibernateListItemWriter hibernateItemWriter=新的HibernateListItemWriter(this.sessionFactory){{{setSessionFactory(sessionFactory);};
返回hibernateItemWriter;
}
我的扩展类看起来是这样的(我可能会清理它,但这是我的第一次通过。我也希望sessionFactory和clearSession字段不是私有的)

package.com.work;
导入java.util.ArrayList;
导入java.util.List;
导入org.hibernate.SessionFactory;
公共类HibernateListItemWriter扩展org.springframework.batch.item.database.HibernateItemWriter{
公共HibernateListItemWriter(SessionFactory SessionFactory){
超级();
this.sessionFactory=sessionFactory;
}
私人会话工厂会话工厂;
私有布尔clearSession=true;
@凌驾
公共无效写入(列表项){
List unwrappedItems=new ArrayList();
列表wrappedItems=(列表)项;
对于(列表单列表:wrappedItems){
unwrappedItems.addAll(singleList);
}
doWrite(sessionFactory,未包装);
sessionFactory.getCurrentSession().flush();
如果(清除会话){
sessionFactory.getCurrentSession().clear();
}
}
}

感谢grepcode.com让生活变得更轻松。

谢谢Michael..通过示例!!
package com.work;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.SessionFactory;

public class HibernateListItemWriter<Receivable> extends org.springframework.batch.item.database.HibernateItemWriter<Receivable> {

    public HibernateListItemWriter(SessionFactory sessionFactory) {
        super();
        this.sessionFactory = sessionFactory;
    }

    private SessionFactory sessionFactory; 
    private boolean clearSession = true;

    @Override
    public void write(List items) {
        List<Receivable> unwrappedItems = new ArrayList<Receivable>();
        List<List<Receivable>> wrappedItems = (List<List<Receivable>>)items;
        for (List<Receivable> singleList: wrappedItems) {
            unwrappedItems.addAll(singleList);
        }
        doWrite(sessionFactory, unwrappedItems);
        sessionFactory.getCurrentSession().flush();
        if(clearSession) {
            sessionFactory.getCurrentSession().clear();
        }
    }

}