我在使用Spring批处理作业读取大型CSV文件(几百万条记录)并将其中的记录保存到数据库时遇到了问题。该作业使用< code>FlatFileItemReader来读取CSV,并使用< code>JpaItemWriter将读取和处理的记录写入数据库。问题是< code>JpaItemWriter在将另一个项目块刷新到数据库后没有清除持久性上下文,作业以< code>OutOfMemoryError结束。
我已经通过扩展JpaItemWriter
并覆盖写入方法解决了这个问题,以便在编写一堆之后调用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();写方法中的
。
作业配置:
@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
(和HibernateItemWriter
)用于清除持久上下文,但它已在BATCH-1635中删除(这是删除它的提交)。但是,这已通过clearSession
参数(请参阅此提交)在BATCH-1759中的HibernateItemWriter
中重新添加并可配置,但在JpaItemWriter
中没有。
因此,我建议针对Spring Batch打开一个问题,以向JpaItemWriter
添加相同的选项,以便在编写项目后清除持久性上下文(这将与HibernateItemWriter
一致)。
也就是说,为了回答您的问题,您确实可以使用自定义编写器来清除持久性上下文。
希望这有所帮助。
问题内容: 我认为我的android应用正在泄漏内存。我不是绝对确定这是问题所在。 应用程序打开时经常崩溃,并且logcat尝试加载位图图像时会显示“内存不足”异常。 崩溃后,我重新打开了该应用程序,它运行正常。Logcat会显示许多“ gc”,并且JIT表会不时地向上调整大小,而不会向下调整,直到应用程序因内存不足错误而崩溃。 这听起来像是内存泄漏吗?如果是这样,我该如何定位和关闭泄漏点。 这是
问题内容: 我一直在追寻内存泄漏(由“ valgrind –leak-check = yes”报告),它似乎来自ALSA。这段代码已经存在于自由世界中一段时间了,所以我猜这是我做错的事情。 输出看起来像这样: 并继续一些页面 这是由于我在一个项目中使用ALSA并开始看到这种巨大的泄漏……或者至少是所说泄漏的报告。 所以问题是:是我,ALSA或valgrind在这里遇到问题吗? 问题答案: ht
问题内容: 我有一个长时间运行的脚本,如果让脚本运行足够长的时间,它将消耗系统上的所有内存。 在不详细介绍脚本的情况下,我有两个问题: 是否有可遵循的“最佳实践”,以防止泄漏发生? 有什么技术可以调试Python中的内存泄漏? 问题答案: 看看这篇文章:跟踪python内存泄漏 另外,请注意,垃圾收集模块实际上可以设置调试标志。看一下功能。此外,请查看Gnibbler的这段代码,以确定调用后已创建
本文向大家介绍Java 内存泄漏,包括了Java 内存泄漏的使用技巧和注意事项,需要的朋友参考一下 在Java中,垃圾回收(析构函数的工作)是使用垃圾回收自动完成的。但是,如果代码中有引用它们的对象怎么办?它无法取消分配,即无法清除其内存。如果这种情况一再发生,并且创建或引用的对象根本没有被使用,它们就会变得无用。这就是所谓的内存泄漏。 如果超过了内存限制,则程序将通过抛出错误(即“ OutOfM
问题内容: 我使用Informix遇到了一个奇怪的问题(具体来说,我使用的是IBM.Data.Informix命名空间,即4.10 Client SDK)。我正在使用ODBC连接到IBM Informix数据库,并且遇到内存泄漏问题。该文档相当稀疏,并且我只能使用当前安装的驱动程序/ SDK。这是我用于数据库上下文的代码: } 我已尝试处置并关闭所有可以的连接,但这似乎无济于事。我是否缺少某些东西
我有一个后台服务正在运行,它正在将数据同步到我的服务器。 泄漏发生在以下代码中: 内存分析器显示: stockserv.datasyncer.jobexecutor@0x135f6550上的线程保留了总大小为18.603.056(37,90%)字节的局部变量。内存累积在“”加载的“java.lang.Object[]”的一个实例中。 JobExecutor->Arraylist->Object[2