Spring batch 复杂批处理{read-write-split-write}

Spring batch 复杂批处理{read-write-split-write},spring-batch,Spring Batch,我有这样的情况——我有一个文件,其中每一行都包含一个文件名或目录名以及操作状态。此文件可能包含数千行。 然后,我应该将文件或目录的名称及其状态写入数据库。最后,我必须写入一个新文件,但是如果一个项目是一个目录,我必须找到这个目录中的所有文件,并写入这些文件的名称,而不是目录名 我认为这是两步工作,第一步是从文件中读取,然后写入数据库,并将项目并行地保存为内存列表中的项目。第二步是从这个内存列表中读取,如果这是一个目录,用读取器中的文件名替换它,然后写入文件 我担心的一件事是在台阶之间夹着成千上万

我有这样的情况——我有一个文件,其中每一行都包含一个文件名或目录名以及操作状态。此文件可能包含数千行。 然后,我应该将文件或目录的名称及其状态写入数据库。最后,我必须写入一个新文件,但是如果一个项目是一个目录,我必须找到这个目录中的所有文件,并写入这些文件的名称,而不是目录名

我认为这是两步工作,第一步是从文件中读取,然后写入数据库,并将项目并行地保存为内存列表中的项目。第二步是从这个内存列表中读取,如果这是一个目录,用读取器中的文件名替换它,然后写入文件

我担心的一件事是在台阶之间夹着成千上万的物体


有谁能提出更优雅的解决方案吗?

我认为你不需要两个步骤。您可以使用单个步骤

你的读者将保持不变 您可以使用processor将目录扩展到文件,也可以在ItemReader中实现 使用委托项编写器并写入数据库和新文件。 下面是批配置示例

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    // tag::readerwriterprocessor[]
    @Bean
    public FlatFileItemReader<String> reader() {
        FlatFileItemReader<String> reader = new FlatFileItemReader<String>();
        reader.setResource(new PathResource("MyFile"));
        reader.setLineMapper(new PassThroughLineMapper());
        return reader;
    }

    @Bean
    public CompositeItemReader<String> cpReader(){
        final CompositeItemReader<String> reader = new CompositeItemReader<>();
        reader.setItemReader(reader());
        return reader;
    }

    @Bean
    public CompositeItemWriter<String> cpWriter(){
        final CompositeItemWriter<String> delegator = new CompositeItemWriter<>();
        delegator.setDelegates(Arrays.asList(fileWriter(), dbWriter()));
        return cpWriter();
    }

    @Bean
    public FlatFileItemWriter<String> fileWriter(){
        return null;
    }

    @Bean
    public JdbcBatchItemWriter<String> dbWriter(){
        return null;
    }

    @Bean
    public ItemWriter<String> writer() {
        final ItemWriter<String> writer = new ItemWriter<String>() {

            @Override
            public void write(List<? extends String> items) throws Exception {
                items.forEach(System.out::println);

            }
        };
        return writer;
    }

    @Bean
    public Job kpJob() {
        return jobBuilderFactory.get("kpJob").incrementer(new RunIdIncrementer()).start(step1()).build();
    }

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1Child").<String, String>chunk(10).reader(cpReader()).writer(cpWriter()).stream(reader()).build();
    }

}
复合式电子阅读器

public class CompositeItemReader implements ItemCountAware, ItemReader<String> {

    private ItemReader<String> itemReader;
    private int count = 1;
    private final LinkedList<String> files = new LinkedList<>();

    public ItemReader<String> getItemReader() {
        return itemReader;
    }

    public void setItemReader(ItemReader<String> itemReader) {
        this.itemReader = itemReader;
    }

    @Override
    public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        return readFile();
    }

    private String readFile()
            throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if (files.size() == 0) {
            final String item = itemReader.read();
            if (item == null) {
                return null;
            } else {
                Path path = Paths.get(item);
                if (Files.isDirectory(path)) {
                    files.addAll((Collection<? extends String>) Files.walk(path, 1).map(Path::toString)
                            .collect(Collectors.toList()));

                } else {
                    files.add(path.toString());
                }
            }
        }
        return files.poll();
    }

    @Override
    public void setItemCount(int count) {
        this.count = count;

    }

}

希望这些基本信息能够继续。

所以,如果有人好奇,我想到了下一个解决方案:在数据库中创建一个新表,用于按原样存储文件中的记录,因此,如果一行包含filename,则存储它,如果一行包含dirname,则也存储它。然后在这个表的帮助下,我可以连接到我的目标表,从特定目录中获取文件名列表

所以,第一步就是从文件中读取并存储到两个表中——新表和目标表


第二步是使用一个只返回文件名的查询从数据库中读取数据,并将这些记录写入文件,而不进行任何拆分/扩展,因为这是由查询完成的

你能详细说明一下吗?例如,我没有得到,因为我必须写入db目录名和dir的文件扩展文件名,如何使用您的解决方案实现这一点?