在 Hibernate 实体持久化期间发生巨大的内存泄漏,为什么?
Huge memory leak during Hibernate entity persisting, why?
我将 Hibernate 与 JPA EntityManager 一起使用,而不是 Hibernate 会话。大多数人似乎都建议为每个事务使用一个新的 EntityManager,所以这就是我正在做的。
因此,我连续创建了 10000 个新实体。第一次迭代的堆使用量约为 90 MB,最后一次迭代为 5 GB。
这是我的迭代代码:
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_ONLY);
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(new AccountTest(account));
changes++;
}
entityManager.close();
accounts.close();
session.close();
还有我的持久化函数:
public class Database
{
private final EntityManagerFactory entityManagerFactory;
public Database(String host, String database, String user, String password)
{
Map<String, Object> properties = new HashMap<String, Object>();
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("default", properties);
}
public EntityManager createEntityManager()
{
return entityManagerFactory.createEntityManager();
}
public void persist(Object... objects)
{
EntityManager entityManager = createEntityManager();
entityManager.getTransaction().begin();
for (Object object : objects) {
entityManager.persist(object);
}
entityManager.getTransaction().commit();
entityManager.clear();
entityManager.close();
}
}
所以我遍历所有帐户实体(10k,但由于滚动功能而使用 Hibernate Session)并想为每个帐户创建一个新的 AccountTest。
问题是您一直保持第一个 EntityManager
打开,而只清除并关闭另一个 EntityManager
,它仅用于保留一个项目。
最后,您在第一个 EntityManager
中加载了所有帐户实体。
我将 Hibernate 与 JPA EntityManager 一起使用,而不是 Hibernate 会话。大多数人似乎都建议为每个事务使用一个新的 EntityManager,所以这就是我正在做的。
因此,我连续创建了 10000 个新实体。第一次迭代的堆使用量约为 90 MB,最后一次迭代为 5 GB。
这是我的迭代代码:
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_ONLY);
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(new AccountTest(account));
changes++;
}
entityManager.close();
accounts.close();
session.close();
还有我的持久化函数:
public class Database
{
private final EntityManagerFactory entityManagerFactory;
public Database(String host, String database, String user, String password)
{
Map<String, Object> properties = new HashMap<String, Object>();
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("default", properties);
}
public EntityManager createEntityManager()
{
return entityManagerFactory.createEntityManager();
}
public void persist(Object... objects)
{
EntityManager entityManager = createEntityManager();
entityManager.getTransaction().begin();
for (Object object : objects) {
entityManager.persist(object);
}
entityManager.getTransaction().commit();
entityManager.clear();
entityManager.close();
}
}
所以我遍历所有帐户实体(10k,但由于滚动功能而使用 Hibernate Session)并想为每个帐户创建一个新的 AccountTest。
问题是您一直保持第一个 EntityManager
打开,而只清除并关闭另一个 EntityManager
,它仅用于保留一个项目。
最后,您在第一个 EntityManager
中加载了所有帐户实体。