转:failed to lazily initialize a collection of role

failed to lazily initialize a collection of role: XXXXXXXX no session or session was closed2007-05-11 10:47这个异常大致意思是说在多对一的时候(并且lazy="false"),对象的实例失败,多数出现的情况有

1、粗心造成

实例对象类名写错之类的

2、逻辑错误

如之前就已经传递过来一个实体对象,然后调用实体对象的方法时牵涉到1对多的情况,但此时SESSION已经关闭,所以根本无法进行一对多的操作。

3、设计到跨度的问题:

这样打比方有多个实体对象,他们直接或则间接的有关联。比如有4个实体,分别是广告信息、广告、广告问答题、广告商:他们之间的关系为:

广告商 1:n 广告

广告 1:n 广告问答题

广告商 1:n 广告商信息

大家可以看到广告和广告商信息是没有直接关系的。但我要添加广告的时候我就必须将广告商的实体做为条件。那么这么一来广告商信息可能间接的就必须用上。下面看我的操作:

ad(广告),subject(题目)

     Ad ad = new Ad();
     ad.setAdProd(adform.getAdProd());
     ad.setIndustry(industry);
     ad.setAdPicture(pagefile.getFileName());
     ad.setAdFlack(adform.getAdFlack());
     ad.setAdDv(dvfile.getFileName());
     ad.setAdContent(adform.getAdContent());
     ad.setGray(gray);
     ad.setAdDate(new Date());
     ad.setOnlinetime(new Long(0));

     //以上为广告的基本信息填写,而重要的是看下面一句,在这里我的思路是subjectFormList是一个动态提交的表单,里面有若干个广告问答题。我将这些问答题变为一个Set,然后作为ad的一个属性。

     Set<Subject> subjectset=getSubjectSet(subjectFormList,ad);
     ad.setSubjects(subjectset);

//然后提交,makePersistent是一个封装的方法,用途就是save()啦。addao是一个DAO,里面有ADUS。

addao.makePersistent(ad);

表面上看来很符合逻辑,只要我们在ad的映射里面加上对subject的级联更新就可以完成这项操作。但实际上会发生我们意想不到的问题,来让我们看一下getSubjectSet()的内容:

public Set getSubjectSet(List<SubjectForm> subjectlist,Ad ad)
{
   Set<Subject> set=new HashSet<Subject>(0);
   Subject subject;
 
   for(Iterator<SubjectForm> it=subjectlist.iterator();it.hasNext();)
   {
    subject=new Subject();
    SubjectForm sf=it.next();
    subject.setSuContent(sf.getSucontent());
    subject.setSuOption(sf.getSuoption());
    subject.setSuResult(Arrays.deepToString(sf.getSuresult()));
    subject.setSuType(String.valueOf(sf.getSutype()));
    subject.setAd(ad);
    set.add(subject);
   }
 
 
   return set;
 
}

我们在这个方法上设一个断点然后跟踪,之后你会发现断点在set.add(subject)只后就会出failed to lazily initialize a collection of role: XXXXXXXX no session or session was closed这个异常,并且这个异常还是出在了广告商的广告信息上 gray.messages。是不是很不可理解?这也是Hibernate的懒汉机制问题。没有任何一样技术是完美的。那我们该怎么处理这样的问题。有很多人以为我们在广告商对广告商信息的隐射上加lazy="false"这样在对gray操作会对messages进行关联,并查询时提出数据。但你会发现改完之后会出现org.hibernate.LazyInitializationException: illegal access to loading collection这个异常。并切lazy="false"是我们不推荐的一种方法。他会降低你的查询效率。

对于这样的情况最好的解决办法就是不要偷懒,对一个实体进行操作的时候就该用那个实体的DAO,即应该有2句HQL。如下把getSubjectSet()改一改:

public void getSubjectSet(List<SubjectForm> subjectlist,Ad ad)
{
   Set<Subject> set=new HashSet<Subject>(0);
   SubjectDAO subjectdao=DAOFactory.getDao(SubjectDAO.class);
 
 
   for(Iterator<SubjectForm> it=subjectlist.iterator();it.hasNext();)
   {
    Subject subject=new Subject();
    SubjectForm sf=it.next();
    subject.setSuContent(sf.getSucontent());
    subject.setSuOption(sf.getSuoption());
    subject.setSuResult(Arrays.deepToString(sf.getSuresult()));
    subject.setSuType(String.valueOf(sf.getSutype()));
    subject.setAd(ad);
    subjectdao.makePersistent(subject);
    //set.add(subject);
   }
 
}//遍历出所有subject一个个的往数据库里加。这样便不会出问题了。



解决方法:

OpenSessionInView模式:

以下有2种方法,第1种是结合SPRING,第2种是采用了拦截器

Spring+Hibernate中,     集合映射如果使用lazy="true", 当PO传到View层时, 出现未初始化session已关闭的错误,只能在dao先初始化

parent.getChilds().size();
Spring提供Open Session In View来解决这个问题, 有两种方式
1. Interceptor        <!--</span><span style="COLOR: rgb(0,128,0)"> =========== OpenSession In View pattern ==============</span><span style="COLOR: rgb(0,128,0)">-->
    <bean id="openSessionInViewInterceptor"
             class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="interceptors" ref="openSessionInViewInterceptor"/>
        <property name="mappings">
            <props>
               ......
            </props>
        </property>
    </bean>

2. Filter

<web-app>

<!-- open session in view filter -->
    <filter>
        <filter-name>OpenSessionInViewFilter</filter-name>
        <!--<filter-class>org.itec.village.filter.SessionManager</filter-class>-->
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>OpenSessionInViewFilter</filter-name>
        <servlet-name>FacesServlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

</web-app>

第2种解决方法:

Hibernate.initialize()强制加载关联对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值