#spring #out-of-memory #spring-batch
Вопрос:
У меня есть таблица MY_TABLE
, которая содержит около 500 тысяч строк, считыватель должен прочитать из этой таблицы pageSize
как 100, затем он должен обработать эту страницу как мой процессор и записать в БД в соответствии с моим автором.
Что происходит, так это то, что читатель продолжает читать на 100 100 страницах до тех пор, пока не выдохнется и не выдаст OutOfMemoryError
около 400 тысяч записей.
Я не уверен, почему это не работает на страницах и chunk
вообще, и почему он считывает все данные из таблицы, а не работает только с pageSize
суммой.
Ниже приведен код, который у меня есть для step
и reader
.
public Step customStep(StepBuilderFactory stepBuilderFactory, ItemReader<CustomEntityClass> reader, ItemProcessor<CustomEntityClass, List<CustomEntityClassSecond>> processor, ItemWriter<List<CustomEntityClassSecond>> writer) { DefaultResultCompletionPolicy comp = new DefaultResultCompletionPolicy(); return stepBuilderFactory.get(BatchConstants.STEP_NAME) .<CustomEntityClass, List<CustomEntityClassSecond>> chunk(comp) .reader(reader) .processor(processor) .writer(writer).build(); } @Bean public Step purgeTasklet(StepBuilderFactory stepBuilderFactory, Tasklet tasklet) { return stepBuilderFactory.get(BatchConstants.TASKLET_NAME).tasklet(tasklet).build(); } @Bean public ItemReader<CustomEntityClass> customReader(@Qualifier(DATA_SOURCE) DataSource dataSource) throws Exception { JdbcPagingItemReader<CustomEntityClass> reader = new JdbcPagingItemReader<>(); SqlPagingQueryProviderFactoryBean pagingQueryFactoryBean = new SqlPagingQueryProviderFactoryBean(); pagingQueryFactoryBean.setSelectClause("*"); pagingQueryFactoryBean.setFromClause("MY_TABLE"); pagingQueryFactoryBean.setWhereClause("CREATIONDATE <= :creationDate"); pagingQueryFactoryBean.setSortKey("id"); pagingQueryFactoryBean.setDataSource(dataSource); reader.setQueryProvider(pagingQueryFactoryBean.getObject()); reader.setPageSize(100); reader.setDataSource(dataSource); reader.setRowMapper(new BeanPropertyRowMapper<>(CustomEntityClass.class)); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, -1); DateFormat df = new SimpleDateFormat(BatchConstants.CREATION_DATE_FORMAT); String creationDate = df.format(calendar.getTime()); Map<String, Object> parameters = new HashMap<>(); parameters.put("creationDate", creationDate); reader.setParameterValues(parameters); return reader; }```
Комментарии:
1. Может ли этот класс быть проблемой здесь для использования в блоке?
DefaultResultCompletionPolicy comp = new DefaultResultCompletionPolicy();
Должен ли я использовать SimpleCompletionPolicy?
Ответ №1:
Размер блока, который использует Spring Batch, не зависит от размера страницы в считывателе. Имеет смысл устанавливать их последовательно, но это не обязательно строго.
Это должно работать, как и ожидалось, с
stepBuilderFactory.get(BatchConstants.STEP_NAME) .<CustomEntityClass, List<CustomEntityClassSecond>>chunk(100) .reader(reader) .processor(processor) .writer(writer).build();
Затем Spring Batch будет использовать 100 элементов на кусок, что в точности соответствует содержимому одной запрашиваемой страницы.
Комментарии:
1. можете ли вы сказать мне, почему вы использовали размер фрагмента int, а не сказали «новая политика simplecompletion(100)»?
2. Это равносильно. Если вы передадите размер блока int, Spring Batch создаст политику для вас. Это дело вкуса, но я бы предпочел передать int, так как это делает код приложения немного более компактным.