确保 EntityManager 连接关闭的正确方法是什么?

发布于 2024-09-11 07:42:48 字数 776 浏览 6 评论 0原文

我们的 DAO 层中有 19 个方法,每个方法都是以下方法的一些变体:

public TicketProp saveTicketProp(TicketProp prop) {
    EntityManager em = this.emf.createEntityManager();
    try {
        em.getTransaction().begin();
        prop = (TicketProp) em.merge(prop);
        em.getTransaction().commit();
        return prop;
    } finally {
        em.close();
    }
}

含义:在每个方法中,我们处理自己的事务并在 finally 块中关闭它。我们正在测试 Jersey 应用程序,因此我们的 JUnit 测试扩展了 JerseyTest。每个测试方法都会实例化一个 Grizzly 容器,运行测试,然后关闭容器。 EntityManagerFactory是由spring注入的。我们使用 JPA 而不是 Hibernate。

我正在监视与 MySQL 测试数据库的连接,它们总是很高。仅一项测试就将 MySQL“Max_used_connections”变量运行为 38。为了好玩,我注释掉了所有 em.close() 调用,测试仍然使用 38 个连接。

我正在使用 Hibernate 的内置连接池(我知道,不用于产品用途)。我仍然期待某种智能池。

我处理 EntityManager 是否错误?我还能如何关闭连接?

There are 19 methods in our DAO layer, each is some variation of this:

public TicketProp saveTicketProp(TicketProp prop) {
    EntityManager em = this.emf.createEntityManager();
    try {
        em.getTransaction().begin();
        prop = (TicketProp) em.merge(prop);
        em.getTransaction().commit();
        return prop;
    } finally {
        em.close();
    }
}

Meaning: In each method we handle our own transaction and close it in a finally block. We're testing a Jersey app, so our JUnit tests extend JerseyTest. Each test method instantiates a Grizzly container, runs the test, then shuts down the container. EntityManagerFactory is injected by spring. We're using JPA over Hibernate.

I'm monitoring the connections to our MySQL test DB and they're always high. One test alone runs the MySQL "Max_used_connections" variable to 38. For fun, I went and commented out all the em.close() calls, and the test still uses 38 connections.

I'm using Hibernate's built-in connection pooling (not for prod use, I know). I still expected some sort of intelligent pooling.

Am I handling the EntityManager wrong? How else can I close connections?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

攀登最高峰 2024-09-18 07:42:48

您应该在测试结束时关闭EntityManagerFactory。来自 的 javadoc EntityManagerFactory#close()

void javax.persistence.EntityManagerFactory.close()

关闭工厂,释放它所拥有的所有资源。关闭工厂实例后,对其调用的所有方法都将抛出 IllegalStateException,但 isOpen 除外,它将返回 false。一旦 EntityManagerFactory 关闭,其所有实体管理器都被视为处于关闭状态。

附带说明一下,您实际上应该在 finally 子句中关闭 EM 之前回滚事务:

public TicketProp saveTicketProp(TicketProp prop) {
    EntityManager em = this.emf.createEntityManager();
    try {
        em.getTransaction().begin();
        prop = (TicketProp) em.merge(prop);
        em.getTransaction().commit();
        return prop;
    } finally {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }

        if (em.isOpen()) {
            em.close();
        }
    }
}

You should close the EntityManagerFactory at the end of your test. From the javadoc of EntityManagerFactory#close():

void javax.persistence.EntityManagerFactory.close()

Close the factory, releasing any resources that it holds. After a factory instance has been closed, all methods invoked on it will throw the IllegalStateException, except for isOpen, which will return false. Once an EntityManagerFactory has been closed, all its entity managers are considered to be in the closed state.

As a side note, you should actually rollback the transaction before closing the EM in the finally clause:

public TicketProp saveTicketProp(TicketProp prop) {
    EntityManager em = this.emf.createEntityManager();
    try {
        em.getTransaction().begin();
        prop = (TicketProp) em.merge(prop);
        em.getTransaction().commit();
        return prop;
    } finally {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }

        if (em.isOpen()) {
            em.close();
        }
    }
}
别闹i 2024-09-18 07:42:48

您为什么认为 EntityManager.close() 总是以物理方式关闭底层连接?这取决于连接池(您可能需要配置它并设置同时打开连接的最大数量)。

Why do you think that EntityManager.close() always physically closes underlying connection? It's up to connection pool (you probably need to configure it and set the maximum number of simultaneously open connections).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文