繁体   English   中英

如何在 Spring-Batch 中使用 ItemReader 跳过行?

[英]How to skip lines with ItemReader in Spring-Batch?

我有一个自定义项目阅读器,可以将文本文件中的行转换为我的实体:

public class EntityItemReader extends AbstractItemStreamItemReader<MyEntity> {
    @Override
    public MyEntity read() {
       String line = delegate.read();
       //analyze line and skip by condition
       //line.split
       //create entity with line values
    }
}

这类似于FlatFileItemReader

然后读取的MyEntity将通过JdbcItemReader持久化到数据库。

问题:有时我的行包含应该跳过的值。

但是,当我在read()器的read()方法中只return null时,不仅会跳过此项目,还会完全终止阅读,并且会跳过所有其他行。 因为null元素是所有 spring-readers 的“信号”,即要读取的文件已完成。

那么:如果我不能返回 null,我该怎么做才能根据阅读器中的条件跳过特定的行? 因为根据读者的性质,我被迫在这里返回一个对象。

我认为过滤某些行的好做法是不使用阅读器,而是使用处理器(当您想过滤该行时,您可以在其中返回 null)。

请参阅http://docs.spring.io/spring-batch/trunk/reference/html/readersAndWriters.html

6.3.2 过滤记录

项目处理器的一个典型用途是在将记录传递给 ItemWriter 之前过滤掉记录。 过滤是一种不同于跳过的动作; 跳过表示记录无效,而过滤仅表示不应写入记录。

例如,考虑读取包含三种不同类型记录的文件的批处理作业:要插入的记录、要更新的记录和要删除的记录。 如果系统不支持记录删除,那么我们不希望向 ItemWriter 发送任何“删除”记录。 但是,由于这些记录实际上并不是坏记录,我们希望将它们过滤掉,而不是跳过。 因此,ItemWriter 将只接收“插入”和“更新”记录。

要过滤记录,只需从 ItemProcessor 返回“null”。 框架将检测结果为“null”并避免将该项目添加到传递给 ItemWriter 的记录列表中。 像往常一样,从 ItemProcessor 抛出的异常将导致跳过。

对于我使用自定义阅读器的更一般情况,我遇到了类似的问题。 这由对象类型上的迭代器支持,并为每个读取的对象返回一个新项目(不同类型)。 问题是其中一些对象没有映射到任何东西,所以我想返回一些标记它的东西。

最终我决定定义一个 INVALID_ITEM 并返回它。 另一种方法可能是在 read() 方法中推进迭代器,直到下一个有效项,如果 .hasNext() 变为 false,则返回 null,但这更麻烦。

最初我也尝试返回一个自定义的 ecxeption 并告诉 Spring 跳过它上面的项目,但它似乎被忽略了,所以我放弃了(如果有太多无效的无论如何都没有性能)。

在这种情况下(以及阅读所有评论后),我认为您不能吃蛋糕并吃掉它。 最好的意见是(按照建议)抛出自定义异常并跳过“在它上面”。 您可以在其他地方优化您的实体创建或流程,这样您就不会失去太多的性能。 祝你好运。

我们可以通过自定义的虚拟对象来处理它。

private final MyClass DUMMYMyClassObject ;

private MyClass(){
   // create blank Object .
}

public static final MyClass getDummyyClassObject(){
  if(null == DUMMYMyClassObject){
      DUMMYMyClassObject = new MyClass();
  }
  return DUMMYMyClassObject ;
 }

当需要跳过阅读器中的记录时,只需使用以下内容:

return MyClass.getDummyyClassObject();

同样可以在处理器中忽略,检查对象是否为空或按照私有默认构造函数中编写的逻辑。

对于跳过行,当您想跳过某些行时可以抛出异常,如下所示。

我的春季批次步骤

@Bean
Step processStep() {

    return stepBuilderFactory.get("job step")
                .<String, String>chunk(1000)
                .reader(ItemReader)
                .writer(DataWriter)
                .faultTolerant() //allowing spring batch to skip line 
                .skipLimit(1000) //skip line limit
                .skip(CustomException.class) //skip lines when this exception is thrown
                .build();
}

我的物品阅读器

@Bean(name = "reader")
public FlatFileItemReader<String> fileItemReader() throws Exception {

    FlatFileItemReader<String> reader = new FlatFileItemReader<String>();

    reader.setResource(resourceLoader.getResource("c://file_location/file.txt"));
    CustomLineMapper lineMapper = new CustomLineMapper();
    reader.setLineMapper(lineMapper);

    return reader;

    }

我的自定义线映射器

public class CustomLineMapper implements LineMapper<String> {

@Override
public String mapLine(String s, int i) throws Exception {

    if(Condition) //put your condition here when you want to skip lines
        throw new CustomException();
    return s;
}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM