2016-08-17 27 views
0

Spring 2.5を使用する古いSpringMVCアプリケーションをSpring 4に変換しています。2.5でうまく機能していたOpenSessionInViewフィルタを取得できません。Spring 2.5からSpring 4へのOpenSessionInViewフィルタの変換

私の状況は、リクエストGETで返されたコマンドオブジェクトがセッションに保存されているということです。このフォームがPOSTされます。一部のサービスレイヤーコードは、最初にフェッチされていないコマンドオブジェクトから、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を動作させる方法を理解したいと思います。

編集: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がnullで、かつallowLoadOutsideTransactionfalseです。これは私が得ている例外がスローされている場所です。

sessionがヌルであるかどうか、またはallowOutsideTransactionが問題であるかどうかを知るには、あまり知りません。

+0

トランザクションを開始する場所を指定していませんが、しかし、それを@Transactionalにマークすると、このフィルタも必要ありません。 –

答えて

0

OpenSessionInViewFilterは、要求の範囲についてセッションを維持します。あなたは2つの要求を保つことについて話していますが、それは問題です。

オブジェクトをhibernateから再取得するか、GET要求処理中にオブジェクトをevictにしてからupdate POST中にセッションに「再接続」することができます。

+0

返事をありがとう。 'OpenSessionInViewFilter'が2.5で動いていて、それが動作していると思われる多くのコードがあるので、それはもっとうまく機能します。すべてのスポットがコード内にある場所を特定するのは難しいです。そして、エラーを待つか、時間を浪費する網羅的な分析を待って、それらのすべてを見つけようとするのではなく、おそらく 'OpenSessionInViewFilter'を手に入れようとする方が簡単かもしれません。 – user2215659

+0

申し訳ありませんが、私は 'OpenSessionInViewFilter'が動作していない場所を逃したと思いますか?上記で説明したシナリオ、複数のリクエストで有効であると思われるセッション、何か他のことが起こっていることを示している場合、 'OpenSessionInViewFilter'はこれを行いません。 – Taylor

関連する問題