Spring Batch: разбиение на страницы JdbcPagingItemReader - PullRequest
0 голосов
/ 30 марта 2020

Возникла проблема, когда я делал простой пакет, который считывает данные из базы данных postgresql, обрабатывает и записывает в CSV-файл. Далее читатель:

 @Bean
@StepScope
public ItemReader<SearchResult> databaseReader(@Qualifier("reportingDataSource") HikariDataSource reportDataSource,
                                           @Value("#{stepExecution}") StepExecution stepExecution) {

    JdbcPagingItemReader<SearchResult> reader = new JdbcPagingItemReader<>();
    reader.setQueryProvider(createQueryProvider());
    reader.setRowMapper(new CustomRowMapper());
    reader.setDataSource(reportDataSource);
    reader.setPageSize(5);
    reader.open(stepExecution.getExecutionContext());
    return reader;
}

private PagingQueryProvider createQueryProvider(SearchTxnRequest searchTxnRequest) {
    SqlitePagingQueryProvider queryProvider = new SqlitePagingQueryProvider();
    queryProvider.setSelectClause("SELECT *");
    queryProvider.setFromClause("from dummy_table");
    queryProvider.setSortKeys(sortBy());
    return queryProvider;
}

private Map<String, Order> sortBy() {
    Map<String, Order> sortConfiguration = new HashMap<>();
    sortConfiguration.put("date", Order.ASCENDING);
    return sortConfiguration;
}

Я вставил фиктивные данные в 'dummy_table' с другим идентификатором, но такими же данными в других полях, включая поле даты. Как видно из кода, функция sortBy определяет способ сортировки информации в таблице, я выбрал только поле даты. Проблема возникает здесь, если все строки в таблице имеют одинаковую дату, пакет возвращает только первые 5 строк (если размер страницы 5).

Почему? ну, JdbcPagingItemReader разбивает на страницы с ключами сортировки, в данном случае только с датой. Отладка показывает следующее: Итак, первая страница читается

2020-03-30 15:01:40 DEBUG [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : Reading page 0
2020-03-30 15:01:40 DEBUG [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : SQL used for reading first page: [SELECT * FROM from dummy_table ORDER BY date ASC LIMIT 5]

Вторая страница:

2020-03-30 15:01:40 [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : Reading page 1
2020-03-30 15:01:40 [nio-7035-exec-1] o.s.b.i.database.JdbcPagingItemReader    : SQL used for reading remaining pages: [SELECT * FROM from dummy_table WHERE ((date > ?)) ORDER BY date ASC LIMIT 5]

Как видно, разбиение на страницы производится с помощью ключа сортировки по дате. Моя проблема заключалась в том, что все данные в таблице имели одинаковую дату. Важно правильно выбрать ключ сортировки, чтобы избежать проблем с нумерацией страниц. Я добавил идентификатор, и это решило проблему.

1 Ответ

0 голосов
/ 30 марта 2020

Вам не нужно вызывать reader.open в вашем методе databaseReader, Spring Batch сделает это, если ваш читатель объявлен как ItemStreamReader. Я рекомендую возвращать наиболее конкретный тип c в определениях bean-компонентов для чтения / записи, чтобы Spring Batch мог правильно создавать прокси. В вашем случае это должно быть что-то вроде:

@Bean
@StepScope
public JdbcPagingItemReader<SearchResult> databaseReader(@Qualifier("reportingDataSource") HikariDataSource reportDataSource) {

   JdbcPagingItemReader<SearchResult> reader = new JdbcPagingItemReader<>();
   reader.setQueryProvider(createQueryProvider());
   reader.setRowMapper(new CustomRowMapper());
   reader.setDataSource(reportDataSource);
   reader.setPageSize(5);
   return reader;
}

Важно правильно выбирать ключ сортировки, чтобы избежать проблем с нумерацией страниц. Я добавил идентификатор, и это решает проблему.

Да, как задокументировано, вот выдержка из Javadocs JdbcPagingItemReader и AbstractSqlPagingQueryProvider :

It is important to have a unique key constraint on the sort key

The columns that make up the sort key must be a true key and not just a column to order by

Я считаю, что ваш столбец даты не является ключевым, поэтому, когда вы добавляете идентификатор, он работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...