Java Hibernate实体持久化期间出现巨大内存泄漏,为什么?

Java Hibernate实体持久化期间出现巨大内存泄漏,为什么?,java,hibernate,jpa,memory-leaks,persistence,Java,Hibernate,Jpa,Memory Leaks,Persistence,我在JPA EntityManager中使用Hibernate,而不是Hibernate会话。大多数人似乎都建议在每笔交易中使用新的EntityManager,所以这就是我正在做的 因此,我在一行中创建了10000个新实体。堆的使用率在第一次迭代时约为90MB,在最后一次迭代时为5GB 这是我的迭代代码: Session Session=Core.getDatabase().createEntityManager().unwrap(Session.class); Query Query=ses

我在JPA EntityManager中使用Hibernate,而不是Hibernate会话。大多数人似乎都建议在每笔交易中使用新的EntityManager,所以这就是我正在做的

因此,我在一行中创建了10000个新实体。堆的使用率在第一次迭代时约为90MB,在最后一次迭代时为5GB

这是我的迭代代码:

Session Session=Core.getDatabase().createEntityManager().unwrap(Session.class);
Query Query=session.getNamedQuery(“Account.getAllIds”);
query.setReadOnly(true);
query.setFetchSize(100);
ScrollableResults accounts=query.scroll(仅限ScrollMode.FORWARD_);
EntityManager EntityManager=Core.getDatabase().createEntityManager();
entityManager.getTransaction().begin();
while(accounts.next()){
int id=(int)accounts.get(0);
Account Account=entityManager.getReference(Account.class,id);
Core.getDatabase().persist(新AccountTest(account));
变化++;
}
entityManager.close();
accounts.close();
session.close();
还有我的持久性函数:

公共类数据库
{
私人最终实体管理工厂实体管理工厂;
公共数据库(字符串主机、字符串数据库、字符串用户、字符串密码)
{
映射属性=新的HashMap();
properties.put(“javax.persistence.jdbc.url”,“jdbc:mysql://“+host+”:3306/“+database”);
properties.put(“javax.persistence.jdbc.user”,user);
properties.put(“javax.persistence.jdbc.password”,password);
entityManagerFactory=Persistence.createEntityManagerFactory(“默认”,属性);
}
公共EntityManager createEntityManager()
{
返回entityManagerFactory.createEntityManager();
}
公共void持久化(对象…对象)
{
EntityManager EntityManager=createEntityManager();
entityManager.getTransaction().begin();
用于(对象:对象){
entityManager.persist(对象);
}
entityManager.getTransaction().commit();
entityManager.clear();
entityManager.close();
}
}

因此,我迭代了所有帐户实体(10k,但由于滚动功能而使用Hibernate会话),并希望为每个帐户创建一个新的AccountTest。

问题是您一直持有第一个打开的
EntityManager
,而仅清除并关闭另一个仅用于持久化一个项目的
EntityManager


最后,您将所有帐户实体加载到第一个
EntityManager

中,这不是内存泄漏,即所谓的会话缓存。你需要了解JPA是如何工作的;em.close();em.finalize();还没有清除缓存?我该打什么电话呢?谢谢你的回答。我使用第一个EM为每个帐户ID调用getReference。我是否应该为每个getReference调用创建一个新EM,或者我甚至可以用“a=new account();a.setId(ID)”替换getReference调用,因为我可以完全确定数据库中存在ID?如果您确定数据库中存在
帐户
,而Hibernate允许您使用设置了id的临时实体引用实体。此功能特定于Hibernate,不是JPA标准。