Spring / Hibernate / Richfaces应用程序中的延迟加载问题

时间:2010-08-11 10:16:48

标签: hibernate spring jsf richfaces lazy-loading

在Spring应用程序中,我使用了带有Hibernate的组件rich:tree,它使用延迟加载显示应用程序的层次结构。 问题是Hibernate会话已关闭,这会阻止延迟加载,并在呈现页面时收到异常。 最后我添加了opensessionViewFilter,它允许我保持会话直到呈现页面。

<filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>sessionFactory</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

这个解决方案部分地解决了页面呈现的问题,并且显示了富:树组件但是当进行ajax调用(节点之间的导航)时,我得到了延迟加载的相同错误:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: myPackage.entities.Module.modules, no session or session was closed
 at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
 at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
 at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
 at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
 at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
 at com.cylande.utilities.TreeNode.getNodes(TreeNode.java:77)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at javax.el.BeanELResolver.getValue(BeanELResolver.java:62)
 at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:54)
 at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
 at org.apache.el.parser.AstValue.getValue(AstValue.java:118)
 at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
 at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71)
 at org.richfaces.component.html.HtmlRecursiveTreeNodesAdaptor.getNodes(HtmlRecursiveTreeNodesAdaptor.java:160)
 at org.richfaces.component.UIRecursiveTreeNodesAdaptor$1.getData(UIRecursiveTreeNodesAdaptor.java:74)
 at org.richfaces.model.StackingTreeModel.getDataModel(StackingTreeModel.java:80)
 at org.richfaces.model.StackingTreeModel.isEmpty(StackingTreeModel.java:107)
 at org.richfaces.model.StackingTreeModel.isLeaf(StackingTreeModel.java:264)
 at org.richfaces.component.UITree.isLeaf(UITree.java:534)
 at org.richfaces.renderkit.html.TreeNodeRenderer.doEncodeBegin(TreeNodeRenderer.java:105)
 at org.richfaces.renderkit.html.TreeNodeRenderer.doEncodeBegin(TreeNodeRenderer.java:86)
 at org.ajax4jsf.renderkit.RendererBase.encodeBegin(RendererBase.java:100)
 at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:813)
 at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:275)
 at org.richfaces.renderkit.TreeRendererBase$DataVisitorWithLastElement.process(TreeRendererBase.java:255)
 at org.richfaces.model.AbstractTreeDataModel.processElement(AbstractTreeDataModel.java:111)
 at org.richfaces.model.StackingTreeModel.doWalk(StackingTreeModel.java:294)
 at org.richfaces.model.StackingTreeModel$Visitor1.process(StackingTreeModel.java:416)
 at org.richfaces.model.StackingTreeModel$ShiftingDataVisitor.end(StackingTreeModel.java:461)
 at org.richfaces.model.StackingTreeModel.doWalk(StackingTreeModel.java:348)
 at org.richfaces.model.StackingTreeModel.walk(StackingTreeModel.java:383)
 at org.richfaces.component.UITree.walk(UITree.java:422)
 at org.richfaces.renderkit.TreeRendererBase.writeContent(TreeRendererBase.java:683)
 at org.richfaces.renderkit.TreeRendererBase.encodeAjaxChildren(TreeRendererBase.java:475)
 at org.ajax4jsf.component.UIDataAdaptor.encodeAjaxChild(UIDataAdaptor.java:454)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:146)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
 at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
 at org.ajax4jsf.renderkit.AjaxContainerRenderer.encodeAjax(AjaxContainerRenderer.java:123)
 at org.ajax4jsf.component.AjaxViewRoot.encodeAjax(AjaxViewRoot.java:680)
 at org.ajax4jsf.component.AjaxViewRoot.encodeChildren(AjaxViewRoot.java:551)
 at javax.faces.component.UIComponent.encodeAll(UIComponent.java:930)
 at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
 at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
 at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
 at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
 at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
 at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
 at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
 at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388)
 at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:70)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
 at java.lang.Thread.run(Thread.java:619)

请帮我看一下ajax组件的延迟加载列表。

这是我的xhtml页面:

<h:form>
            <rich:panel>
                <rich:tree>
                    <rich:recursiveTreeNodesAdaptor roots="#{treeBean.srcRouts}"
                        var="item" nodes="#{item.nodes}">
                    </rich:recursiveTreeNodesAdaptor>
                </rich:tree>
            </rich:panel>

</h:form>

这是Bean:TreeBean.java

public class TreeBean {
private List<TreeNode> srcRouts;
@Autowired
private ApplicationDAO applicationDAO;
@Transactional
public List<TreeNode> getSrcRouts() {
    List<TreeNode> ListNode=new ArrayList<TreeNode>();
    if(srcRouts==null)
    {
        List<Application> list=applicationDAO.findAll();
        for(Application app:list)
        {
            TreeNode treeNode=new TreeNode();
            treeNode.setApplication(app);
            ListNode.add(treeNode);
        }
        srcRouts=ListNode;
    }
    return srcRouts;
}

public void setSrcRouts(List<TreeNode> srcRouts) {
    this.srcRouts = srcRouts;
}
}

这是Bean TreeNode.java:

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import myPackage.entities.Application;
import myPackage.entities.Module;
import myPackage.entities.Page;
import myPackage.services.ApplicationDAO;

public class TreeNode {
    private List<TreeNode> nodes;
    private ApplicationDAO applicationDAO;
    private String libelle;
    private Application application;
    private Module module;
    private Page page;

    public Application getApplication() {
        return application;
    }

    public void setApplication(Application application) {
        this.application = application;
    }

    public Module getModule() {
        return module;
    }

    public void setModule(Module module) {
        this.module = module;
    }

    public Page getPage() {
        return page;
    }

    public void setPage(Page page) {
        this.page = page;
    }

    public String getLibelle() {
        return libelle;
    }

    public void setLibelle(String libelle) {
        this.libelle = libelle;
    }

    public ApplicationDAO getApplicationDAO() {
        return applicationDAO;
    }

    public void setApplicationDAO(ApplicationDAO applicationDAO) {
        this.applicationDAO = applicationDAO;
    }

    public List<TreeNode> getNodes() {
        List<TreeNode> listNoeud = new ArrayList<TreeNode>();
        Set<Module> setModule;
        Set<Page> setPage;
        if (nodes == null) {
            // noeud application
            if (application != null) {
                setModule = this.application.getModules();
                for (Module module : setModule) {
                    if(module.getModule()==null){
                    TreeNode treeNode = new TreeNode();
                    treeNode.module = module;
                    listNoeud.add(treeNode);
                }
                }
            }
            // noeud module
            else if (module != null) {
                setModule = this.module.getModules();
                for (Module module : setModule) {
                    TreeNode treeNode = new TreeNode();
                    treeNode.module = module;
                    listNoeud.add(treeNode);
                }
                setPage = this.module.getPages();
                for (Page page : setPage) {
                    TreeNode treeNode = new TreeNode();
                    treeNode.page = page;
                    listNoeud.add(treeNode);
                }
            }
            nodes=listNoeud;
        }

        return nodes;
    }

    public void setNodes(List<TreeNode> nodes) {
        this.nodes = nodes;
    }

    public String toString() {
        String libelle="";

        // noeud application
        if (application != null) {
            libelle = application.getNomApplication();
        }
        // noeud module
        else if (module != null) {
            libelle = module.getNomModule();
        }
        // noeud page
        else if (page != null) {
            libelle = page.getNomPage();
        }
        return libelle;
    }
}

我使用组件树来显示要测试的用户添加的应用程序...实际上尝试创建一个运行用户选择的测试的应用程序。 要指定,我的节点是应用程序,模块或页面

这是我的Generic DAO:

import java.io.Serializable;
import java.util.List;

import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class GenericDAOHibernateImpl<T, PK extends Serializable> implements
        GenericDAO<T, PK> {
    private Class<T> type;
    @Autowired
    private HibernateTemplate hibernateTemplate;

    public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }

    public GenericDAOHibernateImpl(Class<T> type) {
        this.type = type;
    }

    public PK create(T o) {
        return (PK) getHibernateTemplate().save(o);
    }

    public T read(PK id) {
        return (T) getHibernateTemplate().get(type, id);
    }

    public void update(T o) {
        getHibernateTemplate().update(o);
    }

    public void delete(T o) {
        getHibernateTemplate().delete(o);
    }

    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        List<T> toExport = null;
        toExport = (List<T>) getHibernateTemplate().find(
                "from "+ type.getName());
        return toExport;
    }

    @SuppressWarnings("unchecked")
    public T findByID(PK id) {
        T entity = null;
        entity =  (T)getHibernateTemplate().get(type, id);
        return entity;
    }

}

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您至少有两个选项

  • 使用*ToMany
  • 定义集合(fetchType=FetchType.EAGER
  • 在使用Hibernate.initialize(..)
  • “发送”到视图之前手动初始化对象

答案 1 :(得分:2)

我对rich:tree组件没有任何特殊经验,但选项是IMO:

  1. 通过一些DAO方法为给定的父节点id获取子节点。
  2. 使用某种“远程延迟加载”。
  3. 不要使用延迟加载。
  4. 我不认为#3 是“解决方案”。

    对于#2 ,请查看H3T(仔细阅读)。

    要实施#1 Dynamic Trees in JSF帖子可以提供帮助。这将是我的选择。

    进一步阅读