java - Spring Batch 内存泄漏 - 使用 JpaItemWriter 将 CSV 保存到数据库
问题描述
我在读取大型 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();
}
@Bean
public Job appointmentInitJob(@Qualifier("initEclinicAppointments") Step step) {
return jobBuilderFactory.get(JOB_NAME)
.incrementer(new RunIdIncrementer())
.preventRestart()
.start(step)
.build();
}
解决方案
这是一个有效的观点。( JpaItemWriter
and HibernateItemWriter
) 用于清除持久上下文,但已在BATCH-1635中删除(这是删除它的提交)。但是,这已被重新添加并HibernateItemWriter
在BATCH-1759中通过clearSession
参数(请参阅此提交)进行配置,但在JpaItemWriter
.
所以我建议打开一个针对 Spring Batch 的问题以添加相同的选项JpaItemWriter
,以便在写入项目后清除持久性上下文(这将与 一致HibernateItemWriter
)。
也就是说,要回答您的问题,您确实可以像以前一样使用自定义编写器来清除持久性上下文。
希望这可以帮助。
推荐阅读
- visual-studio - 如何为所有解决方案将 EditorConfig 文件导入 Visual Studio?
- javascript - 隐藏 div 中的表在动态附加 tr 时变得可见
- reactjs - Material UI:根据班级影响孩子
- azure-devops - 我可以在 Azure Devops (VSTS) 中恢复已删除的任务组吗?
- g1ant - ✱chrome 或 chrome✱ 有什么区别?
- c++ - 在 ubuntu 中未使用 CMake 和 Cuda 10.1 找到链接器错误 -lcudart
- react-native - 如何在反向反应原生平面列表上检测到顶部
- javascript - 单击具有平滑行为的按钮时滚动到 div
- html - 如何使用 scrollspy 在顶部下拉导航中显示当前部分名称?
- cookies - ADFS 4.0 禁用浏览器 cookie