Spring Batch内存泄漏-使用JpaItemWriter CSV到数据库

时间:2019-02-18 11:57:00

标签: java spring spring-batch

我遇到了一个Spring Batch作业的问题,该作业需要读取一个大型CSV文件(几百万条记录)并将这些记录保存到数据库中。作业使用0xff...ff来读取CSV,使用-1来将已读取和已处理的记录写入数据库。问题在于,FlatFileItemReader在将另一批项目刷新到数据库后并没有清除持久性上下文,并且作业最终以JpaItemWriter结尾。

我已经通过扩展JpaItemWriter并重写了write方法来解决了这个问题,以便在写完一堆之后调用OutOfMemoryError,但是我想知道Spring Batch是否已经解决了这个问题以及问题出在工作配置中。如何正确解决这个问题?

我的解决方案:

JpaItemWriter

您可以在write方法中看到添加的EntityManager.clear()

作业配置:

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;
        }
    }

1 个答案:

答案 0 :(得分:2)

这是一个正确的观点。 JpaItemWriter(和HibernateItemWriter)用于清除持久性上下文,但已在BATCH-1635中删除(此处the commit已将其删除)。但是,已通过HibernateItemWriter参数(请参见此BATCH-1759)在commitclearSession中的JpaItemWriter中对其进行了重新添加和配置,但未在JpaItemWriter中对其进行配置

因此,我建议针对Spring Batch打开一个问题,向HibernateItemWriter添加相同的选项,以便在编写项目后清除持久性上下文(这与GET city_offices/_search { "size" : 10, "query": { "term" : { "office_type" : "secondary" } }, "aggs": { "citizens": { "nested": { "path": "citizens" }, "aggs": { "inner": { "filter": { "term": { "citizens.age": "40" } } , "aggs": { "occupations": { "nested": { "path": "citizens.pets" }, "aggs": { "inner_pets": { "filter": { "term": { "citizens.pets.name": "Casper" } } , "aggs": { "lll": { "reverse_nested": { "path": "citizens" }, "aggs": { "xxx": { "terms": { "field": "citizens.occupation", "size": 10 } } } } } } } } } } } } } } 一致)

也就是说,要回答您的问题,您确实可以像以前一样使用自定义编写器清除持久性上下文。

希望这会有所帮助。