Hibernate实体持续存在时内存大量泄漏,为什么?

时间:2015-05-07 21:45:32

标签: java hibernate jpa memory-leaks persistence

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

所以,我连续创建了10000个新实体。堆使用率在第一次迭代时约为90 MB,在最后一次迭代时约为5 GB。

java memory leak

这是我的迭代代码:

    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。

1 个答案:

答案 0 :(得分:4)

问题是您是否一直打开第一个EntityManager,而只清除和关闭仅用于保留一个项目的另一个EntityManager

最后,您在第一个EntityManager中加载了所有帐户实体。