Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Почему тормозит Hibernate?


Автор: Andrey1 8.12.2008, 14:23
Сотворил страничку, которая отображает данные одной таблицы из небольшой базы через Hibernate JPA.
Проблема в том, что страница отображается слишком медленно :( . 

Насколько я понял, все тормоза случаются в момент:

        emf = Persistence.createEntityManagerFactory("myNameOfPU");
или 
        em = emf.createEntityManager();

Hibernate разве не должен брать entityManager из пула...?

Вопрос, почему таки тормоза и что делать?

Автор: MisterCleric 8.12.2008, 14:41
Слушай, а ты лукап Factory делаешь при каждом вызове?
Это же эквивалент SessionFactory в JPA. Его надо надо один раз создать а дальше из него брать EntityManager, как из SessionFactory Session

Автор: Andrey1 8.12.2008, 14:46
Цитата(MisterCleric @  8.12.2008,  14:41 Найти цитируемый пост)
Слушай, а ты лукап Factory делаешь при каждом вызове?

Я наивно полагал, что Hibernate JPA сам это делает...

Автор: MisterCleric 8.12.2008, 14:52
Из пула берется EntityManager, а EntityManagerFactory - это класс конфигурации ну и провайдер всех JPA делов.
Каждый раз когда ты его запрашивал, происходила переконфигурация твоего JPA-окружения

Автор: Andrey1 8.12.2008, 15:49
Ага, то есть, если EntityManagerFactory запрашивать один раз  в сессии или в application scope, то таких тормозов не будет и Hibernate не нужно никак дополнительно настраивать?

Автор: MisterCleric 8.12.2008, 16:04
А что значит дополнительно настраивать?
Лучше один раз при старте приложения все настроить, а дальше просто работать с базой через сущности

Автор: Andrey1 8.12.2008, 16:29
Вообщем, ясно, что нужно Spring заюзать и хранить фабрику в application scope.

Автор: MisterCleric 8.12.2008, 16:37
ну или как пишут в доке по JPA статический класс.
А вообще не понятно, почему ты не пользуешься возможностями сервера приложений?

Я беру EntityManage

как:

Код

  @PersistenceContext
    protected EntityManager em;


в EJB3 SessionBeans и мне его инджектит контейнер. А сам PersistenceUnit подымает тоже контейнер - это твой EntityManagerFactory

Автор: Andrey1 8.12.2008, 16:56
Цитата(MisterCleric @  8.12.2008,  16:37 Найти цитируемый пост)
Я беру EntityManage как:
  @PersistenceContext


Потому что Tomcat не умеет так делать smile. А Glassfish тормозит.

Автор: powerOn 8.12.2008, 20:32
Цитата(Andrey1 @  8.12.2008,  16:56 Найти цитируемый пост)
Потому что Tomcat не умеет так делать smile. А Glassfish тормозит. 


А как вы тогда собираетесь транзакциями рулить?

Автор: MisterCleric 9.12.2008, 09:55
У EntityManager есть два метода 

getTransaction(), как написано в JavaDoc, то его нужно вызывать не из JPA

и есть метод flush().

по-моему достаточно дял руления транзакциями не в транзакционном контейнере.

Ну а вообще, если все-таки TomCat. То надо посмотреть в сторону Spring. У них есть решения такого типа задач

Автор: Andrey1 9.12.2008, 12:26
Решил через статическую фабрику и Listener:

Код

public class GenericEntityManagerFactory {

    private static EntityManagerFactory emf = null;

    public GenericEntityManagerFactory()
    {
    }

    /**
     * @return the emf
     */
    public static EntityManagerFactory getEmf()
    {
        return emf;
    }

    /**
     * @param aEmf the emf to set
     */
    public static void setEmf(EntityManagerFactory aEmf)
    {
        emf = aEmf;
    }

...

public class HibernateListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
        GenericEntityManagerFactory.setEmf(Persistence.createEntityManagerFactory(CONSTANTS.namePU));
        // Just call the static initializer of that class
    }

    public void contextDestroyed(ServletContextEvent event) {
        GenericEntityManagerFactory.getEmf().close();
    }
}

...


Код

<!--- in web.xml -->

    <listener>
        <listener-class>jpa.util.HibernateListener</listener-class>
    </listener>
...



Сейчас, правда, фабрика перегружается при любом, даже частичном, передеплое...

Автор: powerOn 9.12.2008, 13:44
Цитата(MisterCleric @  9.12.2008,  09:55 Найти цитируемый пост)
У EntityManager есть два метода 

getTransaction(), как написано в JavaDoc, то его нужно вызывать не из JPA

и есть метод flush().

по-моему достаточно дял руления транзакциями не в транзакционном контейнере.


это понятно, что можно писать компоненты которые будут управлять транзакциями в ручную, да вот только такой подход (как аукнится так и) откликнется при написании тестов. Да и код становится прозрачнее если содержит только бизнес логику. К тому же, если что-то за тебя уже написано не надо тратить время на изобретение велосипеда. Поэтому я думаю, что транзакциями нужно рулить декларативно. 

Но если с томката никуда не уйти, то лучше уж использовать spring и не извращаться.

Автор: Andrey1 10.12.2008, 10:47
Цитата(powerOn @  9.12.2008,  13:44 Найти цитируемый пост)
Поэтому я думаю, что транзакциями нужно рулить декларативно. 

Но если с томката никуда не уйти, то лучше уж использовать spring и не извращаться.


Да, возможно эта проблема когда-нибудь станет. 
И тогда я по-настоящему узнаю, зачем люди придумали Spring smile.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)