使用Spring 3.0.2,hibernate3和jsf2让OpenSessionInViewFilter正常工作时遇到了大麻烦。
情景:
有一个BusinessCaseEntity,它包含一些简单的信息属性(string和int类型)和一个映射的EmployeeEntities列表。此列表使用
进行映射取= FetchType.LAZY
首先,我加载所有BusinessCase的列表并在表格中显示它们。为此,我使用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的目的?
我现在很失落,真的很感激一些帮助。
谢谢 - 克里斯
答案 0 :(得分:1)
我放弃了尝试使用Spring的OpenSessionInViewFilter。我已经实现了JSF阶段监听器来完成这项工作,如下所示:http://assenkolov.blogspot.com.br/2008/04/open-session-in-view-with-jsf-and.html。解决方案对我有用。
以下完整帖子(如果链接已死):
我预计快速谷歌会议会立即为这种情况提供标准解决方案,但它并没有这样做。
问题:我希望在View中使用Open Session来获取JSF / Spring应用程序。好吧,我知道在开放会议中有一些可疑的东西,但请相信我,对于这个应用程序,这很好。应用程序最终有可能成为一个portlet,因此我也不想处理portlet和servlet过滤器问题。相反,我想使用JSF提供的方便钩子来打开和关闭hibernate会话 - 阶段监听器。令人高兴的是,Spring提供的OpenSessionInViewFilter揭示了Spring如何处理hibernate会话工厂的技术细节。
结果如下:
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>
答案 1 :(得分:0)