пятница, 11 марта 2011 г.

Разница между Hibernate openSession() и getCurrentSession()

Начала готовиться к собеседованию и делать тестовое приложение. Основной целью было вспомнить как собственно оно все пишется и настраивается в разных фреймворках. Для начала взяла Hibernate. Однако столкнулась с трудностью: в книге, по которой я изучала Hibernate (надеюсь, найду ее и вставлю ссылку) для получения сессии использовалась функция openSession(), а в текущей документации все примеры основаны на другой функции - getCurrentSession(). В SessionFactory есть обе эти функции, но в чем же разница? Поскольку мне предстоит собеседование решила исследовать вопрос.

Ссылки по теме:
Java docs
http://ajava.org/online/hibernate3api/org/hibernate/SessionFactory.html

А вот здесь человек очень хорошо все обьяснил, но по-английски:
http://www.jeevanchaaya.com/2009/04/11/getcurrentsession-or-opensession-a-sessionic-dilema/



Добавлю и от себя пару слов:

В литературе по Hibernate сессия определяется как часть работы (unit of work). Как определить границы этой части? Hibernate нас тут не ограничивает. Можно связать сессию с транзакцией базы данных (на каждую транзакцию открываем новую сессию), однако разработчики фреймворка дают нам возможность в рамках одной сессии проводить несколько транзакций. Теоретически мы можем для всех взаимодействий с базой данных использовать одну сессию (например, для однопользовательского приложения). Ну, это конечно из раздела bad practice, я просто хотела сказать, что разработчик сам решает что считать логической частью работы, и когда открывать-закрывать сессию. Для обеспечения такой гибкости используется openSession()
Однако в большинстве случаев можно выделить единую стратегию открытия-закрытия сессии. Например, для каждой транзакции базы данных открывается или закрывается своя сессия. Или сессия открывается для каждого потока. Для того чтобы реализовать такую единую стратегию открытие сессии делегируется специальному классу (этот класс должен реализовать интерфейс CurrentSessionContext http://ajava.org/online/hibernate3api/org/hibernate/context/CurrentSessionContext.html ). Программист лишь вызывает метод getCurrentSession(), который либо открывает новую сессию, либо возвращает нам уже существующую сессию (когда создается новая сессия - зависит от конкретной реализации CurrentSessionContext).
Кстати, американцы вместо "стратегия открытия-закрытия сессии ..." выражаются более изящно - "scopes the notion of a current session".

Еще одно преимущество использования  getCurrentSession() - нет необходимости заботиться о закрытии сессии. То есть

...
session.flush();
session.close();

мы используем только для openSession(). Для getCurrentSession() сессия закрывается автоматом
В  Hibernate реализации интерфейса CurrentSessionContext есть 3 штуки. Вот список с указанием, какая же стратегия открытия сессии используется в реализации:
JTASessionContext - сессия асоциируется с JTA-транзакцией. Насколько я поняла, каждой транзакции - по сессии. Поскольку я не знаю что такое JTA, ничего определенного сказать не могу. Иду изучать. Кстати, нашла в блоге упоминание о "JTA enabled container". Вообще, все что я на данный момент знаю: JTA - не JDBC Transaction.

ManagedSessionContext
ThreadLocalSessionContext - каждому треду - по сессии. Обеспечивается это путем хранения открытой сессии в переменной ThreadLocal

Тип используемой реализации указывается декларативно в файле hibernate.cfg.xml таким способом:
<property name="current_session_context_class">thread</property>

В моем проекте для создания обьекта SessionFactory я использую Spring. В данной реализации файл hibernate.cfg.xml отсутствует, а настройка Hibernate производится в xml-файле настройки Spring. В этом случае декларация CurrentSessionContext производится так:

<bean id="hibSessionFactory"      class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" p:dataSource-  ref="dataSource">
     <property name="hibernateProperties">
        <value>
           ...
           hibernate.current_session_context_class=thread
           ...
        </value>
     </property>
</bean>

2 комментария:

  1. Спасибо! Познавательно.

    ОтветитьУдалить
  2. Спасибо, только статья написана плохо! Читаешь начало, да онО! Сейчас я узнаю)) и потом раз ссылки две и "Добавлю и от себя пару слов:" :/

    ОтветитьУдалить