Spring为不同的DB批量读取多个读取器

时间:2017-08-08 18:50:27

标签: spring-boot spring-batch arangodb

我有一个现有的spring批处理项目,它根据启动期间的功能切换决定从MySQL或ArangoDB(NoSql数据库)读取数据并执行一些处理并再次写回MySQL / ArangoDB。

现在,MySQL的阅读器配置如下所示,

@Bean
@Primary
@StepScope
public HibernatePagingItemReader reader(
        @Value("#{jobParameters[oldMetadataDefinitionId]}") Long oldMetadataDefinitionId) {

    Map<String, Object> queryParameters = new HashMap<>();
    queryParameters.put(Constants.OLD_METADATA_DEFINITION_ID, oldMetadataDefinitionId);


    HibernatePagingItemReader<Long> reader = new HibernatePagingItemReader<>();

    reader.setUseStatelessSession(false);
    reader.setPageSize(250);
    reader.setParameterValues(queryParameters);

    reader.setSessionFactory(((HibernateEntityManagerFactory) entityManagerFactory.getObject()).getSessionFactory());
    return reader;
}

我还有另一个像下面这样的arango读者,

@Bean
@StepScope
public ListItemReader arangoReader(
        @Value("#{jobParameters[oldMetadataDefinitionId]}") Long oldMetadataDefinitionId) {

    List<InstanceDTO> instanceList = new ArrayList<InstanceDTO>();

    PersistenceService arangoPersistence = arangoConfiguration
            .getPersistenceService());

    List<Long> instanceIds = arangoPersistence.getDefinitionInstanceIds(oldMetadataDefinitionId);

    instanceIds.forEach((instanceId) ->
    {
        InstanceDTO instanceDto = new InstanceDTO();
        instanceDto.setDefinitionID(oldMetadataDefinitionId);
        instanceDto.setInstanceID(instanceId);
        instanceList.add(instanceDto);

    });

    return new ListItemReader(instanceList);

}

我的步骤配置如下,

@Bean
@SuppressWarnings("unchecked")
public Step InstanceMergeStep(ListItemReader arangoReader, ItemWriter<MetadataInstanceDTO> arangoWriter,
        ItemReader<Long> mysqlReader, ItemWriter<Long> mysqlWriter) {

    Step step = null;
    if (arangoUsage) {
        step = steps.get("arangoInstanceMergeStep")


                .<Long, Long>chunk(1)

                .reader(arangoReader)

                .writer(arangoWriter)


                .faultTolerant()


                .skip(Exception.class)


                .skipLimit(10)

                .taskExecutor(stepTaskExecutor())

                .build();


        ((TaskletStep) step).registerChunkListener(chunkListener);
    }
    else {
        step = steps.get("mysqlInstanceMergeStep")


                .<Long, Long>chunk(1)

                .reader(mysqlReader)

                .writer(mysqlWriter)

                .faultTolerant()

                .skip(Exception.class)


                .skipLimit(failedSkipLimit)

                .taskExecutor(stepTaskExecutor())

                .build();


        ((TaskletStep) step).registerChunkListener(chunkListener);

    }

    return step;
}

MySQL阅读器通过HibernatePagingItemReader提供分页支持,这样它就可以处理数百万个项目而不会出现任何内存问题。

我想为arango阅读器实现相同的分页支持,每次迭代只能获取250个文档,如何修改arango阅读器代码来实现这一目标?

1 个答案:

答案 0 :(得分:0)

首先,ListItemReader的文档说 - 对测试有用所以不要将它用于制作。从所有读者bean而不是实际的具体类型返回ItemReader

话虽如此,Spring Batch API或Spring Data似乎并不支持Arango DB。我能找到的最近的是this

(之前我没有和Arango DB合作过)。

所以在我看来,你必须编写自己的自定义arango阅读器,通过实现抽象类来实现分页 - org.springframework.batch.item.database.AbstractPagingItemReader

如果通过扩展上面的类不可行,你可能必须从头开始实现所有内容。 Spring Batch API中的所有分页读者都扩展了这个抽象类,包括HibernatePagingItemReader

另外,请记住arango记录集应该有某种排序来实现分页,这样我们就可以区分page-0&amp;第-1页等(类似于ORDER BY子句,BETWEEN运算符&amp; less,大于SQL中的运算符等。另外FETCH FIRST XXX ROWS OR LIMIT子句类似于也需要)。

由您自己实施并不是一项非常艰巨的任务,因为您必须计算总可能的项目,订购它们然后分成页面并一次只获取一页。

查看API的实现,例如 - HibernatePagingItemReader等,以获取想法。

希望它有所帮助!!