繁体   English   中英

OpenSessionInView过滤器从Spring 2.5到Spring 4的转换

[英]OpenSessionInView filter conversion from Spring 2.5 to Spring 4

我正在将使用Spring 2.5的旧SpringMVC应用程序转换为Spring4。我无法使OpenSessionInView过滤器正常工作,该过滤器在2.5中运行良好。

我的情况是我有一个命令对象,该对象在Request GET中返回,然后存储在Session中。 此表格已过帐。 然后,某些服务层代码尝试从命令对象中读取最初未获取的集合,从而导致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对象并且看起来不错。

稍后在我的Controller代码中,将调用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是否应该为null还是在这里不是很熟悉,或者是否是allowOutsideTransaction是问题。

OpenSessionInViewFilter保留会话的请求范围。 您正在谈论保留两个请求,这是有问题的。

您应该从休眠中重新获取对象,或者可以在GET请求处理期间evict该对象,然后update它以在POST期间将其“重新连接”到会话。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM