web进修之—Hibernate 懒加载(6)

关于懒加载

在关系数据库设计的时候,我们很多时候把表之间的关系设置为强关联(使用外键进行约束),在Hibernate中利用对象的包含关系进行维护(HIbernate本身就是面向对象的数据库操作模式),例如class有很多student,我们在查询class的时候如果我们把class对应的student都查询出来,student很多的话效率是很低的,但是我们并不会用到class对应的student,这个时候我们希望不去查询student,只有在用到的时候再去查询。这就是Hibernate的懒加载存在的原因——不立即去查询数据库,先使用一个代理对象,在用到的时候再去查询数据库(如果对应的Session还open的话)。

在进行详细介绍之前,先理解一下代理:

代理:Hibernate动态生成的一个类,继承自需要代理的实体类,所以如果实体类要用到懒加载就不能声明为final的。

优点:

减少不必要的查询,提高与数据库交互的效率

缺点:

在使用懒加载后,如果我们需要把student返回前台,但是这个时候session已经关闭,Hibernate不能根据代理对象查询数据库,这个时候再使用student的时候会报LazyInitializationException。

懒加载的配置

lazy(指定抓取时机,什么时候去数据库查询)

用在<class>标签上(只是说明在使用load本类的时候的加载策略):

  • true:默认的取值,使用懒加载
  • false:不使用懒加载

用在<set>、<list>上

  • true:默认取值,使用到该集合里面的元素时才查询
  • false:不使用懒加载,直接查询
  • extra:如果调用的是size/contains方法的时候不去查询,在真正使用里面的元素的时候才查询

用在<one-to-one>和<many-to-one>上

  • false:不使用懒加载策略
  • proxy:默认取值,在使用到的时候才进行查询
  • no-proxy:(很少使用,需编译时期字节码增强)在使用到关联对象的属性(或者其get、set方法)的时候才会查询,使用关联对象的普通方法的时候不会查询,但是编译的时候需要字节码增强(就是在类进行编译的时候使用一定方式增加类的字节码,用来丰富字节码的内容,增强字节码以实现特定的功能,比如我们这儿生成可供hibernate 进行懒加载所需要的功能,编译时期增强字节码的方式有:JVM代理,第三方类加载器),例如
  1. class Person{   
  2.     private Card card = null;   
  3.     // setter& getter   
  4. }   
  5.   
  6. class Card{   
  7.     private String number;   
  8.     // setter & getter   
  9.     public void upgrade(){   
  10.         // TODO   
  11.     }   
  12. }   
  13. class Test{   
  14.     public static void main(String[] args){   
  15.         Person p = (Person)session.get(Person.class, 1);   
  16.         // 会访问数据库   
  17.         p.getCard().getNumber();   
  18.         // 不会访问数据库   
  19.         p.getCard().upgrade();   
  20.     }   
  21. }  

fetch(指定抓取方式,怎么查询数据)

  • join:使用表连接的方式抓取,使用join的时候lazy配置失效
  • select:查询的时候另外发送一条select语句

出现懒加载的情况

使用load单个对象,这个对象会被懒加载

比如session.get(student.class, 1),student会被懒加载,使用getId的时候不回去查询数据库,因为id是由Hibernate维护的

使用<one-to-one>

查询主对象,默认使用join进行连接查询,不使用懒加载,

查询从对象默认使用懒加载,先发送一条select查询从对象,在使用到的时候再发送一条select查询主对象

使用<many-to-one>

查询多的一方的时候使用懒加载(使用Hibernate的时候,而不是JPA)

使用<set>/<list>

默认使用懒加载

懒加载问题解决

在开始的时候我们说了懒加载出现的问题,下面给出三种懒加载的解决方案

方法一:使用Hibernate.initialize(object)

在session未关闭之前调用该方法初始化想要加载的对象,例如

Hibernate.initialize(student);

Hibernate.initialize(student.getCourses());

方法二:重新关联到session

当对象处于脱管的状态,使用lock方法重新关联到session,转化为持久态

  1. //直接重新关联     
  2. session.lock(object, LockMode.NONE);     
  3. //进行版本检查后关联     
  4. session.lock(object, LockMode.READ);     
  5. //使用SELECT ... FOR UPDATE进行版本检查后关联     
  6. session.lock(object, LockMode.UPGRADE);    

方法三:使用OPenSessionInView

OpenSessionInViewFilter一个filter,这个filter把session绑定到当前请求线程上,只要在请求的生命周期内,就可以访问懒加载的对象。配置:

  1. <filter>     
  2.     <filter-name>hibernateOpenSessionInViewFilter</filter-name>     
  3.     <filter-class>org.springside.modules.orm.hibernate.OpenSessionInViewFilter</filter-class>     
  4.     <init-param>     
  5.         <param-name>flushMode</param-name>     
  6.         <param-value>AUTO</param-value>     
  7.     </init-param>     
  8. </filter>     
  9. <filter-mapping>     
  10.     <filter-name>hibernateOpenSessionInViewFilter</filter-name>     
  11.     <url-pattern>/*</url-pattern>     
  12. </filter-mapping>   

参考:

http://www.cnblogs.com/linbaoji/archive/2009/01/07/1370919.html

http://blog.csdn.net/yaorongwang0521/article/details/7074573

特别感谢以上文章的作者,如若有冒犯或者侵权的地方,请及时联系本人修改。

原文地址:https://www.cnblogs.com/sunshine-2015/p/5350055.html