2014-08-29 5 views
2

Я в процессе обновления приложения к Hibernate 4.2 из 3.3. Мы также используем Spring 3.1.3 (который мы не можем/не будем обновлять в это время).Некоторые транзакции, не работающие с Spring/Hibernate 4

Некоторые из моих модульных тестов теперь неудачу с

org.hibernate.HibernateException: No Session found for current thread 

в SpringSessionContext. Это не проблема, поскольку <tx:annotation-driven /> определяется в неправильном контексте или случае отсутствия библиотек CGLIB. Большинство тестов действительно работают, а это значит, что в большинстве случаев работает проксирование транзакций.

Случаи, когда он сейчас не работает, похоже, связаны с использованием типов NOT_SUPPORTED, NEVER и SUPPORTED. По какой-то причине SpringSessionContext не создает сеанс в этих случаях.

В наших случаях использования иногда требуется, чтобы границы транзакций строго не совпадали с границами методов, и что сеансы иногда оживляют транзакции. В случае Spring 3/Hibernate 3 контекст сеанса привязывался к потоку локально, и вызов SessionFactory.getCurrentSession() возвращал экземпляр сеанса, даже если транзакция не была запущена. Это поведение, которое, как мне кажется, все еще имеет место в случае Hibernate 4.

Кто-нибудь знает обходное решение для этого? Трудно выровнять границы сеанса с беседой вместо транзакции, если Spring отказывается создавать сеанс без действительной транзакции. Сессия и ее контекст сохранения не должны быть привязаны к открытой транзакции.

+1

Указанные типы распространения никогда не вызовут создания транзакции или поиска сеанса. Сессия связана с транзакционной границей. Было какое-то обсуждение, если это правильно или нет, и в этой области есть работа, но только для новых версий Spring. –

+0

Почему не требуется работа по распространению? что сделало бы транзакцию, если она не существует, или использовать существующую, что и похоже на то, что вам кажется. –

+0

Propagation.REQUIRED не подходит во всех случаях. Например, у нас есть метод, который выполняет несколько транзакций. Мы установили границу транзакции в методе NEVER или NOT_SUPPORTED, чтобы гарантировать, что транзакция не будет запущена при вызове этого метода. Затем метод использует диспетчер транзакций платформы для начала/фиксации транзакций. Однако даже в этом случае sessionFactory.getCurrentSession() возвращает null и форсирует исключение. Это похоже на довольно серьезную проблему, так как HibernateTransactionManager вводится с той же фабрикой сеансов. – Jeff

ответ

0

работал вокруг этого вопроса путем внедрения CurrentSessionContext, который является оберткой SpringSessionContext и заимствуя некоторые изменения кода, которые сделали его в Спринг Framwork 4+:

public class ClassLoaderSpringSessionContext implements CurrentSessionContext { 

    private final SessionFactoryImplementor sessionFactory; 
    private final SpringSessionContext sessionContext; 

    public ClassLoaderSpringSessionContext(final SessionFactoryImplementor sessionFactory) { 
     this.sessionFactory = sessionFactory; // This is actually some class loading logic that isn't important to this transaction problem. 
     this.sessionContext = new SpringSessionContext(this.sessionFactory); 
    } 

    @Override 
    public Session currentSession() throws HibernateException { 
     try { 
      return sessionContext.currentSession(); 
     } catch (HibernateException e) { 
      if (TransactionSynchronizationManager.isSynchronizationActive()) { 
       Session session = this.sessionFactory.openSession(); 
       if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { 
        session.setFlushMode(FlushMode.MANUAL); 
       } 
       SessionHolder sessionHolder = new SessionHolder(session); 
       TransactionSynchronizationManager 
         .registerSynchronization(new SpringSessionSynchronization(sessionHolder, 
          this.sessionFactory)); 
       TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder); 
       sessionHolder.setSynchronizedWithTransaction(true); 
       return session; 
      } else { 
       throw new HibernateException(
         "Could not obtain transaction-synchronized Session for current thread"); 
      } 
     } 
    } 
} 

SpringSessionSynchronization был пакет частного класса весной 4, поэтому мне также пришлось вытащить версию этого как частный внутренний класс в ClassLoaderSpringSessionContext.

Надеюсь, это поможет кому-то еще.

Смежные вопросы