春季批处理不处理所有记录

时间:2019-10-16 08:45:17

标签: spring spring-boot spring-batch batch-processing spring-batch-tasklet

我正在使用Spring Batch使用RepositoryItemReader从postgresql DB中读取记录,然后将其写入主题。 我看到大约有100万条记录需要处理,但并没有处理所有记录。 我已将阅读器的pageSize设置为10,000,并且与提交间隔(块大小)相同

@Bean
public TaskletStep broadcastProductsStep(){
    return stepBuilderFactory.get("broadcastProducts")
            .<Product, Product> chunk(10000)
            .reader(productsReader.repositoryItemReader())
            .processor(productsProcessor)
            .writer(compositeItemWriter)                    
            .faultTolerant()
            .skip(Exception.class)                              
            .skipLimit(100000)
            .processorNonTransactional()                        
            .listener(new SkipListenerProducts())               
            .listener(productsChunkListener)
            .build();
}


@Bean
public RepositoryItemReader repositoryItemReader() {

    RepositoryItemReader<Product> repositoryReader = new RepositoryItemReader<>();

    try {
        repositoryReader.setRepository(skuRepository);
        repositoryReader.setMethodName("findByIsUpdatedAndStatusCodeIn");
        repositoryReader.setPageSize(10000);
        repositoryReader.setSaveState(false);

        List<List<String>> arguments = new ArrayList<>();
        arguments.add(Stream.of(SkuStatus.RELEASED.getValue().toString(), SkuStatus.BLOCKED.getValue().toString(),
                SkuStatus.DISCONTINUED.getValue().toString())
                  .collect(Collectors.toList()));
        repositoryReader.setArguments(arguments);

        Map sorts = new HashMap();
        sorts.put("catalog_number", Sort.Direction.ASC);

        repositoryReader.setSort(sorts);
        repositoryReader.afterPropertiesSet();

    } catch (Exception exception){
        exception.printStackTrace();
    }

    return repositoryReader;
}

@Query(value = "SELECT * FROM CATALOG.PRODUCTS WHERE IS_UPDATED = 'true' AND STATUS_CODE IN (:statusCode)",
       countQuery = "SELECT COUNT(*) FROM CATALOG.PRODUCTS WHERE IS_UPDATED = 'true' AND STATUS_CODE IN (:statusCode)",
       nativeQuery = true)
public Page<Product> findByIsUpdatedAndStatusCodeIn(@Param(value = "statusCode") List<String> statusCode, 
        Pageable pageable);

1 个答案:

答案 0 :(得分:0)

问题可能是您在混用分页并更新阅读器查询(IS_UPDATED)的条件。

在db中页面大小= 2行和6行的示例

  • IS_UPDATED = true
  • B IS_UPDATED = true
  • C IS_UPDATED = true
  • D IS_UPDATED = true
  • E IS_UPDATED = true
  • F IS_UPDATED = true

第一页读取= 1条返回线A和B

执行写程序后(将A和B的IS_UPDATED设置为false),我们在db中:

  • C IS_UPDATED = true
  • D IS_UPDATED = true
  • E IS_UPDATED = true
  • F IS_UPDATED = true

二读将移至第2页,因此它将以E&F行而不是C&D

任何一个:

  1. 您不应更新IS_UPDATED列。
  2. 或者您创建RepositoryItemReader的子类,并在其中覆盖getPage
    @Override
    public int getPage() {
        return 0;
    }

选项2对于批处理崩溃/错误更具弹性,但是您必须确保在编写器中IS_UPDATED始终设置为false,否则读取器将无限期循环。

如果您使用的是多线程步骤,那么选项2也需要更多调整。