在SSH进行数据库查询操作,有两张表是一对多的关系,我建立的是双向关系,但当使用service层调用dao层,去取HashSet集合属性时,报failed to lazily initialize a collection of role: cn.ittrain.model.User.orders, no session or session was closed,这个意思我明白,是因为spring 进行hibernate的session管理造成的,但我不知道如何让session能在web层继续保持,如果该配置文件的lazy="false"当然是可行的,但这并不是理想的解决方案,希望高手指教!

解决方案 »

  1.   

    看看这个能否帮忙:
    public Object load(Class entityClass, Serializable id) throws DataAccessException {   
            return load(entityClass, id, null);   
        }   
      
        public Object load(final Class entityClass, final Serializable id, final LockMode lockMode)   
                throws DataAccessException {   
      
            return executeWithNativeSession(new HibernateCallback() {   
                public Object doInHibernate(Session session) throws HibernateException {   
                    if (lockMode != null) {   
                        return session.load(entityClass, id, lockMode);   
                    }   
                    else {   
                        return session.load(entityClass, id);   
                    }   
                }   
            });   
        }  public Object load(Class entityClass, Serializable id) throws DataAccessException {
    return load(entityClass, id, null);
    } public Object load(final Class entityClass, final Serializable id, final LockMode lockMode)
    throws DataAccessException { return executeWithNativeSession(new HibernateCallback() {
    public Object doInHibernate(Session session) throws HibernateException {
    if (lockMode != null) {
    return session.load(entityClass, id, lockMode);
    }
    else {
    return session.load(entityClass, id);
    }
    }
    });
    }
    ===============通过实体类的具体名称和标识属性查找指定的记录================ 
    Java代码 
    public Object load(String entityName, Serializable id) throws DataAccessException {   
        return load(entityName, id, null);   
    }   
      
    public Object load(final String entityName, final Serializable id, final LockMode lockMode)   
            throws DataAccessException {   
      
        return executeWithNativeSession(new HibernateCallback() {   
            public Object doInHibernate(Session session) throws HibernateException {   
                if (lockMode != null) {   
                    return session.load(entityName, id, lockMode);   
                }   
                else {   
                    return session.load(entityName, id);   
                }   
            }   
        });}   public Object load(String entityName, Serializable id) throws DataAccessException {
    return load(entityName, id, null);
    } public Object load(final String entityName, final Serializable id, final LockMode lockMode)
    throws DataAccessException { return executeWithNativeSession(new HibernateCallback() {
    public Object doInHibernate(Session session) throws HibernateException {
    if (lockMode != null) {
    return session.load(entityName, id, lockMode);
    }
    else {
    return session.load(entityName, id);
    }
    }
    });}==========根据实体类的类型查询出所有的记录=============================== 
    Java代码 
    public List loadAll(final Class entityClass) throws DataAccessException {   
            return (List) executeWithNativeSession(new HibernateCallback() {   
                public Object doInHibernate(Session session) throws HibernateException {   
                    Criteria criteria = session.createCriteria(entityClass);   
                    prepareCriteria(criteria);   
                    return criteria.list();   
                }   
            });   
        }  public List loadAll(final Class entityClass) throws DataAccessException {
    return (List) executeWithNativeSession(new HibernateCallback() {
    public Object doInHibernate(Session session) throws HibernateException {
    Criteria criteria = session.createCriteria(entityClass);
    prepareCriteria(criteria);
    return criteria.list();
    }
    });
    }Load的所有方法正如上面所列举的 大家可以看到load和get方法还是很相似的。抛开得到list和void方法不说,在得到单个记录的方法上用法是一样的,不过内部是不同的所以他们还是有很大区别的,所以这里我主要是要对get和load方法做一个比较。 
    Get和load方法的比较 
    就我现在的理解,我总结可以分成显性区别和隐性区别 
    显性区别: 
    首先,我还是不配置opensessioninview,整合ssh,spring在action中注入业务层的接口(personService),对俩个方法进行测试。 
     Get方法 
    记录存在时-----可以成功得到记录。 
    记录不存在时返回null, 
    配置opensessioninview效果一样 
     Load方法 
    出现异常: 
    javax.servlet.ServletException: org.hibernate.LazyInitializationException: could not initialize proxy - no Session 之后我配置opensessioninview, 
    记录存在------可以成功得到记录。 
    记录不存在,出现异常 
    javax.servlet.ServletException: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [domain.person.Person#2] 
    隐性区别 
    相比显性区别,隐性区别就是俩中方法的内部实现方式上的不同 
    主要的地方: 
    getHibernateTemplate.load() 存在延迟加载问题。 
    getHibernateTemplate.get()  不存在此问题,她是不采用lazy机制的。 
    1  当记录不存在时候,get方法返回null,load方法产生异常,即get()可以取空的数据集,但load()不行。  
    2  load方法可以返回实体的代理类,get方法则返回真是的实体类 
    3  load方法可以充分利用hibernate的内部缓存和二级缓存中的现有数据,而get方法仅仅在内部缓存中 
    进行数据查找,如果没有发现数据則将越过二级缓存,直接调用SQL查询数据库。 
    4  也许别人把数据库中的数据修改了,load如何在缓存中找到了数据,则不会再访问数据库,而get则 
    会返回最新数据。 
    loadAll方法 
    我实验的程序中俩个实体间的关系manytoone 
    首先我先实验”一”这端: 
    我设置一端,inverse=true 多的一端lazy=proxy,据说manytoone标签默认的lazy属性就是proxy. 
    不使用opensessioninview一端可以得到记录但是多的一端得不到记录。改为opensessioninview后,俩端都能得到记录。 然后我多端的lazy=false, 
    不使用opensessioninview,多端无法得到数据。使用opensessioninview后得到数据 关于从‘一’端,使用loadall方法的总结,无论‘多’段是否设置lazy加载,为了得到‘多’端的数据都要配置opensessioninview,才能实现。 
    然后,我实验再‘多’的一端使用loadAll方法 
    条件一:多的一端实现lazy=proxy, 
    条件二:不使用opensessioninview 
    结果:多的一端数据加载正常,‘一‘端出现异常 
    条件一:多的一端实现lazy=proxy 
    条件二:使用opensessioninview 
    结果:俩端都正常加载,但是通过一端在加载多端为null 
    条件一:多的一端实现lazy=false 
    条件二:不使用opensessioninview 
    结果:俩端都加载正常,不过通过一端再加载多端出现lazy异常 
    条件一:多的一端实现lazy=false 
    条件二:使用opensessioninview 
    结果:俩端都正常加载。 总结:loadall方法真的很麻烦,目前还没有弄清楚,所以尽量少用。