Подтвердить что ты не робот

Обновление до Hibernate 4.1 и "печально известного" HibernateTemplate

Я обновляю наш проект с Hibernate 3.0 до Hibernate 4.1.6. (И мы в настоящее время используем spring 3.1)

Я читал во многих статьях и в документации HibernateTemplate, что с версии 4.0 HibernateTemplate не поддерживается и что я должен заменить его использование вызовом sessionFactory.getCurrentSession(), чтобы получить сеанс.

Поскольку этот проект был запущен со старой версией Hibernate, где было рекомендовано использовать HibernateTemplate, в настоящее время у нас есть 124 использования HibernateTemplate в нашем проекте. Я боюсь, что замена всех этих случаев с помощью sessionFactory.getCurrentSession() может привести к ошибкам регрессии в нашем проекте. Кроме того, есть несколько мест, где HibernateTemplate использовался в не транзакционном контексте, где нет текущего сеанса. Что я должен делать в этих случаях? Откройте новый сеанс и обработайте (закройте) его самостоятельно? Это было не так, когда я использовал HibernateTemplate.

Есть ли у вас хорошая стратегия для решения этих проблем?

Спасибо.

Соответствующее чтение:

4b9b3361

Ответ 1

Хорошо, Так вот что я на самом деле делал, я не знаю, является ли это лучшим решением для этой проблемы, но в наших условиях, и поскольку я искал наиболее локализованное решение, мне это показалось лучше.

Я расширил springframework.orm.hibernate3.HibernateTemplate и создал новый MyHibernateTemplate. Основная роль нового шаблона - переопределить метод doExecute, который в конечном итоге приведет к большей части hibernate3.HibernateTemplate, а также предоставит некоторые функции, которые были предоставлены старыми SessionFactoryUtils (например, isSessionTransactional и applyTransactionTimeout).

Новый doExecute реплицирует логику старого, но вместо SessionFactoryUtils.getNewSession для получения сеанса сначала попытается найти открытый сеанс getSessionFactory(). getCurrentSession():

boolean newSessionOpened = false;
Session session;

if (enforceNewSession){
    session = SessionFactoryUtils.openSession(getSessionFactory());
    newSessionOpened = true;
} else {
    try {
        // look for an open session
        session = getSessionFactory().getCurrentSession();
    }
    catch (HibernateException ex) {
        try {
            // if there isn't an open session, open one yourself
            session = getSessionFactory().openSession();
            newSessionOpened = true;
        } catch (HibernateException e) {
            throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
        }
    }
}

// is the open session, is a session in a current transaction?
boolean existingTransaction = (!enforceNewSession &&
        (!isAllowCreate() || isSessionTransactional(session, getSessionFactory())));

Вам просто нужно закрыть этот сеанс вручную:

    finally {
    // if session was used in an existing transaction restore old settings
    if (existingTransaction) {
        //logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
        disableFilters(session);
        if (previousFlushMode != null) {
            session.setFlushMode(previousFlushMode);
        }
    }
    // if not and a new session was opened close it
    else {
        // Never use deferred close for an explicitly new Session.
        if (newSessionOpened) {
            SessionFactoryUtils.closeSession(session);
            //_log.info("Closing opened Hibernate session");
        }
    }

Я стараюсь держать этот ответ коротким, но если есть какие-то вопросы, я могу подробнее остановиться на этой проблеме.

Ответ 2

Отметьте этот раздел в документах. В нем говорится, что SessionFactory.getCurrentSession() является подключаемым, и существует ThreadLocalSessionContext реализация, которая удерживает "текущий сеанс" в ThreadLocal, а не JTA. ThreadLocalSessionContext также закрывает сеанс в конце транзакции спящего режима, созданной на этом сеансе, поэтому вам не нужно беспокоиться о закрытии Session самостоятельно.

Что касается введения ошибок регрессии, обновление библиотеки всегда будет иметь риск, особенно, когда это что-то вроде вашего приложения как спящего режима. Единственный совет, который я могу дать, - обеспечить, чтобы ваш набор тестов имел достойный охват до обновления. В конце концов, что работа вашего тестового набора - поймать ошибки регрессии.