У меня есть пакетный процесс Spring, который читает данные с сервера SQL и записывает в файл. Используемый мной запрос возвращает 350000 строк и занимает около 2 минут для запуска на SQL Server studio - поэтому запрос настроен для лучшей производительности.
Ниже приведен класс JobConfiguration:
@Configuration
@Slf4j
public class JobConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final FileProperties fileProperties;
private JobProperties jobProperties;
private FileUtility fileUtility;
private CompensationDetailStatusRepository compensationDetailStatusRepository;
private CompensationDetailsRepository compensationDetailsRepository;
@Autowired
public JobConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory,
JobProperties jobProperties, FileProperties fileProperties
) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
this.jobProperties = jobProperties;
this.fileProperties = fileProperties;
}
@Bean
public Job processExtractJob(ExtractProcessListener listener,
Step processExtract,
Step moveFiles
) {
return jobBuilderFactory.get("processExtractJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.start(processExtract)
.on("COMPLETED")
.to(moveFiles)
.end()
.build();
}
@Bean
public Step processExtract(ItemReader<Person> PersonReader,
ExtractProcessor extractProcessor,
ExtractWriter extractWriter
) {
return stepBuilderFactory.get("processExtract")
.<Person, ExtractVO>chunk(50)
.faultTolerant()
.retryLimit(1)
.retry(IOException.class)
.retry(UncheckedIOException.class)
.reader(PersonReader)
.processor(extractProcessor)
.writer(extractWriter)
.build();
}
@Bean
public ExtractWriter extractWriter() {
return new ExtractWriter();
}
@Bean
public ExtractProcessor extractProcessor() {
return new ExtractProcessor();
}
@Bean
public Step moveFiles() {
return stepBuilderFactory.get("moveFiles")
.tasklet((contribution, chunkContext) -> {
fileUtility.moveFiles(String.format("%s*", fileProperties.getFileNamePrefix()),
fileProperties.getFileStagingPath(), fileProperties.getFileTargetPath());
return RepeatStatus.FINISHED;
}).build();
}
@Bean
@StepScope
public ItemReader<Person> PersonReader(EntityManagerFactory entityManagerFactory) {
String query = "Select new com.example.Person (DTL.personId,DTL.description) FROM DETAIL DTL;";
JpaPagingItemReader<Person> reader = new JpaPagingItemReader<>();
reader.setQueryString(query);
reader.setTransacted(false);
reader.setPageSize(jobProperties.getReaderPageSize());
reader.setEntityManagerFactory(entityManagerFactory);
reader.setPageSize(jobProperties.getReaderPageSize());
return reader;
}
@Bean
public ExtractProcessListener jobExecutionListener() {
return new ExtractProcessListener();
}
}
Ниже представлен объект java (Person. java) для набора результатов базы данных:
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PersonCompensation {
private String personId;
private String description;
}
Когда Я запускаю пакетный процесс, я получаю следующее исключение:
2020-04-15 21:34:59.172 ERROR 11748 --- [rTaskExecutor-1] o.s.batch.core.step.AbstractStep : Encountered an error executing step processExtract in job processExtractJob
org.springframework.batch.core.step.skip.NonSkippableReadException: Non-skippable exception during read
at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:105) ~[spring-batch-core-3.0.8.RELEASE.jar:3.0.8.RELEASE]
at org.springframework.batch...
Caused by: java.lang.NullPointerException: null
at org.springframework.batch.item.database.JpaPagingItemReader.doReadPage(JpaPagingItemReader.java:196) ~[spring-batch-infrastructure-3.0.8.RELEASE.jar:3.0.8.RELEASE]
at org.springframework.batch.item.database.AbstractPagingItemReader.doRead(AbstractPagingItemReader.java:108) ~[spring-batch-infrastructure-3.0.8.RELEASE.jar:3.0.8.RELEASE]
at org.springframework.batch.item.support...
... 27 common frames omitted
2020-04-15 21:34:59.946 WARN 11748 --- [rTaskExecutor-1] o.s.b.f.support.DisposableBeanAdapter : Invocation of destroy method 'close' failed on bean with name 'scopedTarget.personCompensationReader': org.springframework.batch.item.ItemStreamException: Error while closing item reader
2020-04-15 21:35:00.277 ERROR 11748 --- [rTaskExecutor-1] o.s.batch.core.job.AbstractJob : Encountered fatal error executing job
org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:140) ~[spring-batch-core-3.0.8.RELEASE.jar:3.0.8.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306) ~[spring-batch-core-3.0.8.RELEASE.jar:3.0.8.RELEASE]
at org.springframework.batch.core...
Caused by: org.springframework.batch.core.job.flow.FlowExecutionException: Next state not found in flow=processExtractJob for state=processExtractJob.processExtract with exit status=FAILED
at org.springframework.batch.core.job.flow.support.SimpleFlow.nextState(SimpleFlow.java:230) ~[spring-batch-core-3.0.8.RELEASE.jar:3.0.8.RELEASE]
at org.springframework.batch.core...
Exit Code: FAILED
Exit Desc: org.springframework.batch.core.step.skip.NonSkippableReadException: Non-skippable exception during read
at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:105)
at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:116)
at org.springframework.batch...
Caused by: java.lang.NullPointerException
at org.springframework.batch.item.database.JpaPagingItemReader.doReadPage(JpaPagingItemReader.java:196)
at org.springframework.batch.item.database.AbstractPagingItemReader.doRead(AbstractPagingItemReader.java:108)
at org.springframework.batch.item...
... 27 more
У меня есть три вопроса:
- Запрашивает ли весенний пакетный процесс и получает все 350000 строк одновременно и передать записи процессору кусками по 50 (размер куска)?
- У меня есть эта строка в коде
JpaPagingItemReader<Person> reader = new JpaPagingItemReader<>();
. Должен ли класс Person быть объектом Entity для того, чтобы это работало, или любой из них будет нормально работать POJO? - Что может быть причиной вышеуказанного исключения?