hibernate 中lazy作用

转载: 

 

HIBERNATE的持久化对象加载策略。
延迟加载, 也就是用到的时候才去加载.这样可以提高一些性能.
Hibernate
lazy loading 采用了一个HibernateSession来管理session,它的逻辑是每进行一次数据库操作,就开新的session,操作完成后立即关闭该session。这样做的好处是可以严格关闭session,避免菜鸟级的错误,但是hibernate.org并不推荐这么做。因为这不适合lazy loading,也不适合跨方法的事务。

比如在我们的应用中,user->post形成一对多的映射,User中有一个包含postList

User中,有多个属性:namepasswordphone等,还有一个List类型的posts。当我们对posts使用lazy laoding的时候,hibernate会在获得User对象的时候,仅仅返回name,password,phone等基本属性,当你访问posts的时候,它才会从数据库中提取posts需要的数据,这就是所谓lazy laoding。但是在我们的系统中,session是被立即关闭的,也就是在读取了name,password,phone等基本属性后,session已经close了,再进行lazy loaiding
就会有异常。
解决办法是在close session之前,调用Hibernate.initialize(user.getPosts()),告诉系统,user.getPosts()是需要lazy laoding的。但是这样做会破坏HibernateSession
类的封装.
后来采用所谓的OpenSessionInView模式,把session的周期交给servlet filter来管理,每当有request进来,就打开一个sessionresponse结束之后再关闭它,这样可以让session存在于整个请求周期中。

本文主要针对一对多情况下读取父类的子集合时,hibernate 的lazy属性在其中的影响进行总结。(以下代码运行在jdk1.5,jboss eclipse ide 1.5,hibernate 3.1环境下)
假设有:父类 Person   (含有Set类型属性Address),
                 子类 Address(碰巧集合的名字和子类的名字都是Address,不要混淆了)
                  Person.hbm.xml   主要片段:
         <id
             name="idx"
             column="idx"
             type="long"
         >
             <generator class="identity">
             </generator>
         </id>
         <property
             name="age"
             type="int"
             update="true"
             insert="true"
             column="age"
         />
         <property
             name="name"
             type="java.lang.String"
             update="true"
             insert="true"
             column="name"
         />
         <set
             name="address"
             table="address"
             lazy="true"
             cascade="none"
             sort="unsorted"
         >
             <key
             >
                 <column
                     name="personidx"
                 />
             </key>
             <one-to-many
                   class="com.abc.common.pojo.Address"
             />

         </set>
     (1)在session 的周期内,无论lazy 设为true or false, 不会有任何限制。访问父子数据的代码如下所示 :       
      //打开session  
      session = HibernateUtil.currentSession();

      PersonDAO dao = new PersonDAO();
      Person person = null;

      person = (Person)dao.findByPrimaryKey(4);
      Set addressSet = person.getAddress();

     Address[] addressAry = new Address[addressSet.size()];
     Address address = null ;
     addressSet.toArray(addressAry);
    
     for(int i=0 ;i<addressAry.length;i++){
                     ................      
      }
    //session关闭
     session.close();
      if (session.isOpen()){
           HibernateUtil.closeSession();
     }

(2)在session的周期外,访问父子数据的代码如下所示 :
      //打开session  
      session = HibernateUtil.currentSession();

      PersonDAO dao = new PersonDAO();
      Person person = null;

      person = (Person)dao.findByPrimaryKey(4);
      /**********************
       *留待后续处理
       *********************/
      session.close();
    
      //session关闭之后才访问person的子集
      Set addressSet = person.getAddress();

     Address[] addressAry = new Address[addressSet.size()];
     Address address = null ;
     addressSet.toArray(addressAry);
    
     for(int i=0 ;i<addressAry.length;i++){
                     ................      
      }
      if (session.isOpen()){
           HibernateUtil.closeSession();
     }

    此时,上述代码的运行结果根据lazy的设置的不同而不同
lazy=false
    结果:可以访问得到Person和Address的数据
lazy= true
     根据代码的写法有不同
     (1)代码其他处不做任何处理,则抛出异常
          org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
          。。。。。。
     (2)如果做一些处理如下,将上述那段代码中的"留待后续处理"换成以下代码
            Hibernate.initialize(person.getAddress());   则可以访问得到Person和Address的数据
          实际编写时,不会象上述这样的写法,即将
          Hibernate.initialize(person.getAddress());和person.getAddress()在同一个方法里面调用。他们往往出现在应用程序的不同层次中(前者出现在DAO层居多,而后者则出现在web层居多).

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值