Как правильно обеспечить закрытие соединений EntityManager? - PullRequest
5 голосов
/ 28 июля 2010

В нашем слое 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. Мы тестируем приложение на Джерси, поэтому наши тесты JUnit расширяют JerseyTest. Каждый метод тестирования создает экземпляр контейнера Grizzly, запускает тест и затем закрывает контейнер. EntityManagerFactory вводится весной. Мы используем JPA вместо Hibernate.

Я отслеживаю соединения с нашей тестовой БД MySQL, и они всегда высокие. Один только тест запускает переменную «Max_used_connections» в MySQL до 38. Ради интереса я пошел и закомментировал все вызовы em.close (), и в этом тесте все еще используются 38 соединений.

Я использую встроенный пул соединений Hibernate (я знаю, что не для использования в prod). Я все еще ожидал какого-то интеллектуального объединения.

Я неправильно обращаюсь с EntityManager? Как еще я могу закрыть соединения?

Ответы [ 2 ]

5 голосов
/ 28 июля 2010

Вы должны close EntityManagerFactory в конце теста . От Javadoc EntityManagerFactory#close():

void javax.persistence.EntityManagerFactory.close()

Закройте фабрику, освободив все имеющиеся у нее ресурсы. После того, как экземпляр фабрики был закрыт, все методы, вызванные на нем, выдают IllegalStateException, кроме isOpen, который возвращает false. После закрытия EntityManagerFactory все его менеджеры сущностей считаются находящимися в закрытом состоянии.

В качестве примечания следует откатить транзакцию перед закрытием EM в предложении finally:

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();
        }
    }
}
2 голосов
/ 28 июля 2010

Почему вы думаете, что EntityManager.close() всегда физически закрывает основную связь?Это зависит от пула соединений (вам, вероятно, потребуется настроить его и установить максимальное количество одновременно открытых соединений).

...