我在读取大型 CSV 文件(几百万条记录)并将记录从中保存到数据库时遇到了 Spring Batch 作业的问题。该作业FlatFileItemReader用于读取 CSV 并将JpaItemWriter读取和处理的记录写入数据库。问题是JpaItemWriter在将另一块项目刷新到数据库并且作业以OutOfMemoryError.
我已经通过扩展JpaItemWriter和覆盖 write 方法解决了这个问题,以便它EntityManager.clear()在编写一堆之后调用,但我想知道 Spring Batch 是否已经解决了这个问题并且问题的根源在于作业配置。如何以正确的方式解决这个问题?
我的解决方案:
class ClearingJpaItemWriter<T> extends JpaItemWriter<T> {
private EntityManagerFactory entityManagerFactory;
@Override
public void write(List<? extends T> items) {
super.write(items);
EntityManager entityManager = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
if (entityManager == null) {
throw new DataAccessResourceFailureException("Unable to obtain a transactional EntityManager");
}
entityManager.clear();
}
@Override
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
super.setEntityManagerFactory(entityManagerFactory);
this.entityManagerFactory = entityManagerFactory;
}
}
您可以entityManager.clear();在 write 方法中看到添加的内容。
作业配置:
@Bean
public JpaItemWriter postgresWriter() {
JpaItemWriter writer = new ClearingJpaItemWriter();
writer.setEntityManagerFactory(pgEntityManagerFactory);
return writer;
}
@Bean
public Step appontmentInitStep(JpaItemWriter<Appointment> writer, FlatFileItemReader<Appointment> reader) {
return stepBuilderFactory.get("initEclinicAppointments")
.transactionManager(platformTransactionManager)
.<Appointment, Appointment>chunk(5000)
.reader(reader)
.writer(writer)
.faultTolerant()
.skipLimit(1000)
.skip(FlatFileParseException.class)
.build();
}
aluckdog
相关分类