博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
web进修之—Hibernate 懒加载(6)
阅读量:7013 次
发布时间:2019-06-28

本文共 3743 字,大约阅读时间需要 12 分钟。

关于懒加载

在关系数据库设计的时候,我们很多时候把表之间的关系设置为强关联(使用外键进行约束),在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代理,第三方类加载器),例如
view plain copy to clipboard print
  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. }  
class Person{    private Card card = null;    // setter& getter}class Card{    private String number;    // setter & getter    public void upgrade(){        // TODO    }}class Test{    public static void main(String[] args){        Person p = (Person)session.get(Person.class, 1);        // 会访问数据库        p.getCard().getNumber();        // 不会访问数据库        p.getCard().upgrade();    }}

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,转化为持久态

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

方法三:使用OPenSessionInView

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

view plain copy to clipboard print
  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>   
hibernateOpenSessionInViewFilter
org.springside.modules.orm.hibernate.OpenSessionInViewFilter
flushMode
AUTO
hibernateOpenSessionInViewFilter
/*

参考:

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

转载于:https://www.cnblogs.com/sunshine-2015/p/5350055.html

你可能感兴趣的文章
RabbitMQ学习总结(7)——Spring整合RabbitMQ实例
查看>>
off文件格式(Object File Format)
查看>>
解答VS2013编译报错不准确是什么原因
查看>>
ajax的post请求
查看>>
阅读笔记《构建之法》一
查看>>
POJ 3140
查看>>
Hive on spark实践
查看>>
批量判断网页是否NOT found
查看>>
富文本编辑器特性
查看>>
Android 虚拟机 程序安装目录
查看>>
oc内容5大区
查看>>
react组件生命周期
查看>>
深入学习Hive应用场景及架构原理
查看>>
[开源]KJFramework.Message 高性能二进制消息框架 - 多元素数组的高性能优化
查看>>
Codeforces Round #333 (Div. 2)
查看>>
构造 BestCoder Round #52 (div.2) 1001 Victor and Machine
查看>>
07-01 Java 封装
查看>>
NSOperation的并发与非并发
查看>>
莫比乌斯反演题目列表及题解
查看>>
linux中常用时间和字符串之间相互转化
查看>>