• Hibernate 延迟载入


    一、延迟载入定义

            
           延迟载入,也叫懒载入,它是Hibernate为提高程序运行效率而提供的一种机制,即当仅仅有真正使用该对象的数据时才会创建。

    说白了,所谓的延迟载入不是在load的时候去数据库载入数据。而是当我在应用程序中真正使用该数据时Hibernate才去查询、载入对应的数据。



    二、延迟载入实现原理

            
           Hibernate中主要是通过代理(proxy)机制来实现延迟载入。即Hibernate丛数据库获取某一个对象数据时、获取某一 个对象的集合属性值时。或获取某一个对象所关联的还有一个对象时。因为没有使用该对象的数据。hibernate并非数据库载入真正的数据,而仅仅是为该对 象创建一个代理对象来代表这个对象。这个对象上的全部属性都是默认值;仅仅有在真正须要使用该对象的数据时才创建这个真实对象,真正从数据库中载入它的数据。
           如:
          User user=(User)session.load(clazz, id);
          System.out.println(user.getId());
          user.getName();
          运行前两句代码时直接返回的是代理对象,没有发送sql语句到数据库载入。这样生成的代理对象具有与真实对象同样的属性和方法,仅仅是在实例化的时候仅仅实例化了该对象的id,当真正使用该对象的其它属性和方法时(运行第三句代码),才创建真实的User实例,并发送sql语句到数据库中载数据,这样大大节省了内存。
     

    三、延迟载入应用环境

           
            当我们要訪问的数据量过大时。明显用缓存不太合适, 由于内存容量有限 。为了降低并发量。降低系统资源的消耗,这时Hibernate用懒载入机制来弥补这样的缺陷,可是这仅仅是弥补而不是用了懒载入整体性能就提高了。
           

         实现懒载入的条件

           
           1 实体类不能是final的 
           2 能实现懒载入的对象都是被CGLIB(反射调用)改写的代理对象,所以不能是final修饰的
           3 需要asm,cglib两个jar包
           4 对应的lazy属性为true
           5 对应的fetch属性为select 

         Hibernate实现的懒载入:


    1、   通过Session.load()实现懒载入
           load(Object, Serializable):依据id查询 。查询返回的是代理对象。不会立马訪问数据库,是懒载入的。当真正去使用对象的时候才会訪问数据库。

          使用load()时假设在session关闭之后再查询此对象,会报异常:could not initialize proxy - no Session。处理办法:
          a.在session关闭之前初始化一下查询出来的对象:Hibernate.initialize(user);
          b.在web.xml中配置OpenSessionInView过滤器就可以解决
    <!-- OpenSessionInView 配置。解决Hibernate延迟载入的问题 -->
      <filter>
       <filter-name>lazyLoadingFilter</filter-name>
       <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
      </filter>
     
    <filter-mapping>
       <filter-name>lazyLoadingFilter</filter-name>
       <url-pattern>*.do</url-pattern>
      </filter-mapping>

    2、   one-to-one(元素)实现了懒载入。

           在一对一的时候,查询主对象时默认不是懒载入。

    即:查询主对象的时候也会把从对象查询出来。须要把主对象配制成lazy="true" constrained="true"  fetch="select"。此时查询主对象的时候就不会查询从对象。从而实现了懒载入。

     
    3、   many-to-one(元素)实现了懒载入。
           多对一的时候,查询主对象时默认是懒载入。即:查询主对象的时候不会把从对象查询出来。多对一的时候,查询从对象时默认是懒载入。

    即:查询从对象的时候不会把主对象查询出来。

           hibernate3.0中lazy有三个值,true。false,proxy,默认的是lazy="proxy".详细设置成什么要看你的需求。并非说哪个设置就是最好的。在<many-to-one>与<one-to-one>标签上:当为true时,会有懒载入特性,当为false时会产生N+1问题,比方一个学生相应一个班级,用一条SQL查出10个学生,当訪问学生的班级属性时Hibernate会再产生10条SQL分别查出每一个学生相应的班级.
    fetch= 捉取方式:select=关联查询;join=连接表的方式查询(效率高),fetch=join时,lazy的设置将没有意义.
     
    4、   one-to-many(元素)懒载入:默认会懒载入,这是必须的,是重经常使用的。

            一对多的时候。查询主对象时默认是懒载入。

    即:查询主对象的时候不会把从对象查询出来。 

    须要配置主对象中的set集合lazy="false" 这样就配置成是不懒载入了。或者配置抓取方式fetch="join"也能够变成不懒载入。

     

    四、总结

           
           依据以上总结我们发现,在Hibernate的延迟载入机制中,大部分是针对集合类型(关联映射设置多的一方延迟载入)的应用意义最为重大。由于这有可能使性能得到大幅度的提高。而Hibernate 的延迟载入(lazy load)本质上就是代理模式的应用。通过代理模式来减少系统的内存开销、提升应用的执行性能。Hibernate 充分利用了代理模式的这样的优势,并结合了 Javassist 或 CGLIB 来动态地生成代理对象。这更加添加了代理模式的灵活性。仅仅只是Hibernate 给这样的使用方法一个新名称:延迟载入。

    不管怎样,分析、了解这些开源框架的实现能够更好的体会到这些经典设计模式的优势所在。



  • 相关阅读:
    解读基础设施即代码
    在那江南烈日与阵雨中-江南100赛记
    写在2017年环汶川越野赛之前
    阿里巴巴Java开发手册评述
    一个程序员的2016年总结
    面向对象的思考过程第四版译者序
    以敏捷的方式运作一所大学
    敏捷团队中的QA由来
    Spring Batch在大型企业中的最佳实践
    Java基础 awt Button 鼠标放在按钮上背景颜色改变,鼠标离开背景颜色恢复
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6735412.html
Copyright © 2020-2023  润新知