2016-08-17 2 views
0

Я конвертирую старое приложение SpringMVC, которое использует Spring 2.5 для Spring 4. Я не могу заставить фильтр OpenSessionInView работать, что хорошо работает в версии 2.5.Преобразование фильтра OpenSessionInView с Spring 2.5 на Spring 4

Моя ситуация в том, что у меня есть объект команды, возвращенный в запросе GET, который затем сохраняется в сеансе. Эта форма POSTED. Некоторый код уровня обслуживания затем пытается прочитать коллекцию из объекта команды, которая не была выбрана изначально, что приводит к LazyInitializationException.

Ошибка я получаю это:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.abc.model.Entity1.details, could not initialize proxy - no Session 

web.xml:

<filter> 
    <filter-name>hibernateFilter</filter-name> 
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> 
    <init-param> 
     <param-name>sessionFactoryBeanName</param-name> 
     <param-value>sessionFactory</param-value> 
    </init-param> 
</filter> 

.... 

<filter-mapping> 
    <filter-name>hibernateFilter</filter-name> 
    <url-pattern>*.html</url-pattern> 
</filter-mapping> 

hibernateFilter перечислен первым в <filter-mapping> порядке.

В моей Hibernate.Xml я получил следующее:

<alias name="abcSessionFactory" alias="commonSessionFactory"/> 
<alias name="abcSessionFactory" alias="instrSessionFactory"/> 
<alias name="abcSessionFactory" alias="sessionFactory"/> 

<!-- Hibernate SessionFactory --> 
<bean id="abcSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="abcDataSource"/> 
    <property name="mappingLocations"> 
     <list> 
      <value>classpath*:/org/abc/model/*.xml</value> 
      <value>classpath*:/org/abc/common/model/*.xml</value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> 
      <prop key="hibernate.show_sql">false</prop> 
      <prop key="hibernate.cache.use_query_cache">true</prop> 
      <prop key="hibernate.cache.use_second_level_cache">true</prop> 
      <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> 
      <prop key="hibernate.cache.provider_class">org.hibernate.cache.OSCacheProvider</prop> 
     </props> 
    </property> 
</bean> 

<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="abcSessionFactory"/> 
    <property name="nestedTransactionAllowed" value="true"/> 
</bean> 

<alias name="txManager" alias="transactionManager"/> 

Я предположил бы, что там должно быть больше конфигурации, но я в недоумении.

Я пробовал использовать свойство hibernate.enable_lazy_load_no_trans, и это действительно сработало. Но это похоже на такой общий взлом, и поэтому я действительно хотел бы выяснить, как заставить OpenSessionInViewFilter работать.

Edit:

От OpenSessionInViewFilter:

SessionFactory sessionFactory = lookupSessionFactory(request); 
    boolean participate = false; 

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 
    String key = getAlreadyFilteredAttributeName(); 

    if (TransactionSynchronizationManager.hasResource(sessionFactory)) { 
     // Do not modify the Session: just set the participate flag. 
     participate = true; 
    } 
    else { 
     boolean isFirstRequest = !isAsyncDispatch(request); 
     if (isFirstRequest || !applySessionBindingInterceptor(asyncManager, key)) { 
      logger.debug("Opening Hibernate Session in OpenSessionInViewFilter"); 
      Session session = openSession(sessionFactory); 
      SessionHolder sessionHolder = new SessionHolder(session); 
      TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); 

      AsyncRequestInterceptor interceptor = new AsyncRequestInterceptor(sessionFactory, sessionHolder); 
      asyncManager.registerCallableInterceptor(key, interceptor); 
      asyncManager.registerDeferredResultInterceptor(key, interceptor); 
     } 
    } 

Трассировка через здесь, то session объект создается и, кажется, хорошо.

Позже в моем коде контроллера вызывается код PersistentSet, чтобы попытаться загрузить соответствующую коллекцию. От AbstractPersistentCollection:

private <T> T withTemporarySessionIfNeeded(LazyInitializationWork<T> lazyInitializationWork) { 
    SessionImplementor originalSession = null; 
    boolean isTempSession = false; 
    boolean isJTA = false; 

    if (session == null) { 
     if (allowLoadOutsideTransaction) { 
      session = openTemporarySessionForLoading(); 
      isTempSession = true; 
     } 
     else { 
      throwLazyInitializationException("could not initialize proxy - no Session"); 
     } 
    } 
    else if (!session.isOpen()) { 

... 
... 

session имеет нулевое значение, и allowLoadOutsideTransaction является false. Это то, где Исключение, которое я получаю, бросается.

Я не знаю достаточно, чтобы знать, является ли session нулевым или нет здесь, или если проблема allowOutsideTransaction.

+0

Хотя вы не указали способ, с которого вы начинаете транзакцию. Но если вы помечаете это на @Transactional, вам также не понадобится этот фильтр. –

ответ

0

OpenSessionInViewFilter сохраняет сеанс в объеме запроса. Вы говорите о сохранении двух запросов, что является проблематичным.

Вы должны повторно восстановить объект из спящего режима или вы могли бы evict объект во время обработки запроса GET, а затем update его «повторно подключить» его к сеансу во время POST.

+0

Спасибо за ответ. Скорее, нужно пытаться заставить «OpenSessionInViewFilter» работать, потому что он работает в 2.5, и есть много кода, который, очевидно, зависит от его работы. Трудно определить, где все эти пятна находятся в коде.И поэтому, вместо того, чтобы проходить через и пытаться найти все из них, либо ожидая появления ошибок, либо выполняя длительный исчерпывающий анализ, вероятно, проще просто попытаться заставить работу OpenSessionInViewFilter работать. – user2215659

+0

Извините, я думаю, что я пропустил тогда, когда 'OpenSessionInViewFilter' не работает? Сценарий, описанный выше, сеанс, который является действительным для нескольких запросов, указывает, что что-то еще происходит, 'OpenSessionInViewFilter' не сделает этого и, насколько мне известно, никогда не имеет. – Taylor

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