В связи с выпиливанием из пакета org.springframework.orm.hibernate4 класса HibernateTemplate остро встал вопрос самостоятельного управления жизненным циклом сессии в наших приложениях. С этим возникают сложности. Давайте попробуем разобраться.
Как минимум, начиная с версии Hibernate 3.1, понятие "текущая сессия" привязано к границам текущей транзакции. Сессия открывается при первом вызове getCurrentSession() и закрывается при завершении транзакции. Так же содержимое сессии автоматически синхронизируется с БД (flush) перед коммитом транзакции. Вы можете вызывать метод getCurrentSession() в вашем коде столько раз, сколько нужно, но до тех пор пока транзакция не завершена.
Для включения данного режима необходимо выставить следующие настройки:
Очень важно! Применение данных настроек не означает, что каждая сессия будет автоматически закрываться при завершении транзакции. Речь идет только о сессиях, полученных посредством getCurrentSession(). Если вы в своем коде используете openSession() и управляете сессией самостоятельно, то вам необходимо явно вызывать методы flush() и close().
При использовании управляемых контейнером транзакций (Container-Managed Transactions, CMT) - стандартной функциональности EJB - настройки несколько отличаются: значение свойства hibernate.transaction.factory_class нужно выставить в org.hibernate.transaction.CMTTransactionFactory (org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory для Hibernate 4).
Но что делать, если у нас нет сервера приложений?
Т.к. вне управляемого окружения, в отсутствие JTA, Hibernate не можете присоединить сессию к транзакции, он присоединяет ее к текущему потоку. При первом в потоке вызове getCurrentSession() будет создан специальный прокси-объект, не позволяющий сделать ничего, кроме как стартовать транзакцию. После старта транзакции в сессии возможно выполнение других операций. При завершении транзакции, неважно успешном или нет, текущая сессия автоматически закрывается. Следующий вызов getCurrentSession() снова создаст прокси и ситуация повторится. Таким образом Hibernate создает новые сессии, привязывает их к потокам, но на самом деле сессия имеет время жизни, совпадающее со временем жизни транзакции, т.е. полностью дублируется поведение в управляемом окружении.
Для включения данной стратегии необходимо выставить следующие настройки:
Опять же, применение данных настроек не означает, что каждая сессия будет автоматически закрываться при завершении транзакции. Речь идет только о сессиях, полученных посредством getCurrentSession(). Если вы в своем коде используете openSession() и управляете сессией самостоятельно, то вам необходимо явно вызывать методы flush() и close().
Следует учитывать, что данная стратегия применима в Java SE, при использовании Java EE (по сути - при использовании EJB) нужно подключать JTA и привязывать сессию к транзакции.
Понравилось сообщение - подпишитесь на блог
Как минимум, начиная с версии Hibernate 3.1, понятие "текущая сессия" привязано к границам текущей транзакции. Сессия открывается при первом вызове getCurrentSession() и закрывается при завершении транзакции. Так же содержимое сессии автоматически синхронизируется с БД (flush) перед коммитом транзакции. Вы можете вызывать метод getCurrentSession() в вашем коде столько раз, сколько нужно, но до тех пор пока транзакция не завершена.
Для включения данного режима необходимо выставить следующие настройки:
- hibernate.transaction.manager_lookup_class - указать стратегию, специфичную для вашего сервера приложений;
- hibernate.transaction.factory_class - в значение org.hibernate.transaction.JTATransactionFactory (org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory для Hibernate 4)
Очень важно! Применение данных настроек не означает, что каждая сессия будет автоматически закрываться при завершении транзакции. Речь идет только о сессиях, полученных посредством getCurrentSession(). Если вы в своем коде используете openSession() и управляете сессией самостоятельно, то вам необходимо явно вызывать методы flush() и close().
При использовании управляемых контейнером транзакций (Container-Managed Transactions, CMT) - стандартной функциональности EJB - настройки несколько отличаются: значение свойства hibernate.transaction.factory_class нужно выставить в org.hibernate.transaction.CMTTransactionFactory (org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory для Hibernate 4).
Но что делать, если у нас нет сервера приложений?
Т.к. вне управляемого окружения, в отсутствие JTA, Hibernate не можете присоединить сессию к транзакции, он присоединяет ее к текущему потоку. При первом в потоке вызове getCurrentSession() будет создан специальный прокси-объект, не позволяющий сделать ничего, кроме как стартовать транзакцию. После старта транзакции в сессии возможно выполнение других операций. При завершении транзакции, неважно успешном или нет, текущая сессия автоматически закрывается. Следующий вызов getCurrentSession() снова создаст прокси и ситуация повторится. Таким образом Hibernate создает новые сессии, привязывает их к потокам, но на самом деле сессия имеет время жизни, совпадающее со временем жизни транзакции, т.е. полностью дублируется поведение в управляемом окружении.
Для включения данной стратегии необходимо выставить следующие настройки:
- hibernate.transaction.factory_class - в значение org.hibernate.transaction.JDBCTransactionFactory (org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory для Hibernate 4);
- hibernate.current_session_context_class - в значение thread.
Опять же, применение данных настроек не означает, что каждая сессия будет автоматически закрываться при завершении транзакции. Речь идет только о сессиях, полученных посредством getCurrentSession(). Если вы в своем коде используете openSession() и управляете сессией самостоятельно, то вам необходимо явно вызывать методы flush() и close().
Следует учитывать, что данная стратегия применима в Java SE, при использовании Java EE (по сути - при использовании EJB) нужно подключать JTA и привязывать сессию к транзакции.
Понравилось сообщение - подпишитесь на блог
Комментариев нет:
Отправить комментарий
Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!