【问题标题】:Spring JSF OpenSessionInViewFilterSpring JSF OpenSessionInViewFilter
【发布时间】:2011-06-14 17:54:50
【问题描述】:

我在使用 Spring 3.0.2、hibernate3 和 jsf2 使 OpenSessionInViewFilter 正常工作时遇到了很大的麻烦。

场景:

有一个 BusinessCaseEntity 包含一些简单的信息属性(字符串和 int 类型)和一个映射的 EmployeeEntities 列表。此列表与

映射

fetch=FetchType.LAZY

首先,我加载所有商务案例的列表并将它们显示在表格中。为此,我使用了一个 dao 类。 显示具有简单属性的商业案例。例如,如果我选择一个特定的商业案例,我想展示相关的员工。因此我只想使用 businesscase 对象的 getter 方法 --> getEmployees()

以我对spring和hibernate的简单理解,我知道此时的BusinessCaseEntity与后端的任何spring和hibernate(session)分离,出现了著名的LazyLoadingException。

这就是我认为 OpenSessionInViewFilter 到位的地方。我阅读了很多关于如何使用它的说明,但我仍然无法让它在我的应用程序中运行。

在我的 web.xml 中配置了过滤器,并且我创建了 spring 的 OpenSessionInViewFilter 的一个小子类来为调试目的做一些输出。

然而,当涉及到获取所需数据时,过滤器会打​​开一个新会话,然后引发 LazyLoadException,然后过滤器会关闭会话。为什么会话当前打开时会出现 LazyLoadException?

2011-06-14 19:19:49,734 DEBUG HibernateFilter:239 - Using SessionFactory 'sessionFactory' for OpenSessionInViewFilter
2011-06-14 19:19:49,734 DEBUG HibernateFilter:66 - Opening single Hibernate Session in OpenSessionInViewFilter
Jun 14, 2011 7:19:49 PM com.sun.facelets.FaceletViewHandler handleRenderException
SEVERE: Error Rendering View[/web/caseDetails.xhtml]
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.frivak.cat.db.entities.BusinessCaseEntity.caseClientList, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
LOTS OF STACKTRACE ...
2011-06-14 19:19:49,879 DEBUG HibernateFilter:92 - Closing single Hibernate Session in OpenSessionInViewFilter

我是否误解了 OpenSessionInViewFilter 的用途?

我现在很迷茫,非常感谢一些帮助。

谢谢 - 克里斯

【问题讨论】:

    标签: hibernate spring jsf open-session-in-view


    【解决方案1】:

    我放弃了尝试使用 Spring 的 OpenSessionInViewFilter。我已经实现了 JSF Phase Listeners 来完成这项工作,如下所示:http://assenkolov.blogspot.com.br/2008/04/open-session-in-view-with-jsf-and.html。该解决方案对我有用。

    下面的完整帖子(如果链接已死):

    我希望快速的 google 会话会立即为这种情况提供标准解决方案,但结果并非如此。

    问题:我想要一个 JSF/Spring 应用程序的 Open Session in View。好的,我知道关于开放会话的看法有些可疑,但相信我,对于这个应用程序来说,这很好。应用程序最终有可能变成一个 portlet,所以我不想也处理 portlet 和 servlet 过滤器问题。相反,我想使用 JSF 提供的方便的钩子来打开和关闭休眠会话 - 阶段侦听器。令人高兴的是,Spring 提供的 OpenSessionInViewFilter 揭示了 Spring 如何处理休眠会话工厂的技术细节。

    结果如下:

    public class HibernateRestoreViewPhaseListener implements PhaseListener {
        public void afterPhase(PhaseEvent event) {
    }
    
    protected SessionFactory lookupSessionFactory() {
        FacesContext context = FacesContext.getCurrentInstance();
        ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
        WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        return (SessionFactory) wac.getBean("hibernate-session-factory", SessionFactory.class);
    }
    
    public void beforePhase(PhaseEvent event) {
        SessionFactory sessionFactory = lookupSessionFactory();
        if (!TransactionSynchronizationManager.hasResource(sessionFactory)) {
            Session session = getSession(sessionFactory);
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
        }
    }
    
    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }
    
    protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
        Session session = SessionFactoryUtils.getSession(sessionFactory, true);
        session.setFlushMode(FlushMode.MANUAL);
        return session;
    }
    

    渲染响应阶段完成后会话关闭:

    public class HibernateRenderResponsePhaseListener implements PhaseListener {
    
        public void afterPhase(PhaseEvent event) {
            SessionFactory sessionFactory = lookupSessionFactory();
            SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
            closeSession(sessionHolder.getSession(), sessionFactory);
        }
    
        ...
    
    }
    

    别忘了在 faces-config.xml 中注册监听器

    <lifecycle>
        <phase-listener>
            ...HibernateRestoreViewPhaseListener
        </phase-listener>
        <phase-listener>
            ...HibernateRenderResponsePhaseListener
        </phase-listener>
    </lifecycle>
    

    【讨论】:

      【解决方案2】:

      【讨论】:

      • 嗨,很抱歉我的回答迟了 - 刚刚放了一个短假。我确实使用了一个事务管理器,在我的 applicationContext.xml ''
      猜你喜欢
      • 2011-10-12
      • 1970-01-01
      • 2011-12-21
      • 2012-12-28
      • 2014-07-15
      • 1970-01-01
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多