文档章节

hibernate读书笔记-懒加载《-》

xiaml
 xiaml
发布于 2014/04/09 22:33
字数 1685
阅读 21
收藏 0

         懒加载是指程序推迟访问数据库,这样做可以保证有时候不必要的访问数据库,因为访问一次数据库是比较耗时的。

         一、load方法的懒加载

         先看如下代码段

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_1 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. <span style="font-size:16px;">public class UserManager {  

  2.   

  3.     public static void main(String[] args) {  

  4.         Users user = new Users();  

  5.         user.setBirthday(new Date());  

  6.           

  7.         Name name = new Name();  

  8.         name.setFirstName("guo");  

  9.         name.setLastName("zhao");  

  10.           

  11.         user.setName(name);  

  12.         addUser(user);  

  13.           

  14.         Users users = getUser(user.getId());  

  15.         System.out.println(users.getName());  

  16.           

  17.     }  

  18.       

  19.       

  20.     static Users getUser(int id){  

  21.         Session session = HibernateUtil.getSession();  

  22.         try {  

  23.             Users users = (Users) session.load(Users.class, id);  

  24.             return users;  

  25.         } finally{  

  26.             session.close();  

  27.         }  

  28.     }  

  29.       

  30.     static void addUser(Users users){  

  31.         Session session = null;  

  32.         Transaction tx = null;  

  33.           

  34.         try {  

  35.             session = HibernateUtil.getSession();  

  36.             tx = session.beginTransaction();  

  37.   

  38.             session.save(users);  

  39.             tx.commit();  

  40.         } catch (HibernateException e) {  

  41.             if (tx!=null) {  

  42.                 tx.rollback();  

  43.             }  

  44.             throw e;  

  45.         }finally{  

  46.             if(session!=null){  

  47.                 session.close();  

  48.             }  

  49.         }  

  50.     }  

  51. }</span>  


         上面代码是先增加一个用户、然后再查询这个用户的name组合属性。运行上面的时候,该程序会抛出这样一个异常:

Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session这就是懒加载不能初始化异常。其原因就在于no session。在前面个持久化对象中已经说明:使用load方法时,该方法将具有延迟加载的功能,load方法并不会立即去访问数据库,它会返回一个代理对象,只有当你真正去访问这个对象的时候,它才会去访问数据库。

         通过上面的图,我们看出,hibernate根本就没有select语句,也就是说hibernate没有去访问数据库,所以这个时候你去访问它肯定是没有的。但为什么没有抛出空指针异常?没有抛出空指针异常,也就是说明User对象是存在的,那它是什么呢?通过输出user.getClass()可以看出是这样一个东西:

         class com.hibernate.domain.Users_$$_javassist_5

         这个user就是load返回的代理对象。但是这个对象并不是我们所要的。我们所要的是一个User实例对象。

         那么怎么解决这个问题呢?

         第一种方法:在关闭session之前访问该对象

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_2 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. <span style="font-size:16px;">  static Users getUser(int id){  

  2.         Session session = HibernateUtil.getSession();  

  3.         try {  

  4.             Users users = (Users) session.load(Users.class, id);  

  5.             users.getName();  

  6.             return users;  

  7.         } finally{  

  8.             session.close();  

  9.         }  

  10.     }</span>  

         不过这句话看起来会很奇怪。我们通常会采用如下的方式

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_3 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. <span style="font-size:16px;">  static Users getUser(int id){  

  2.         Session session = HibernateUtil.getSession();  

  3.         try {  

  4.             Users users = (Users) session.load(Users.class, id);  

  5.             Hibernate.initialize(users);  

  6.             return users;  

  7.         } finally{  

  8.             session.close();  

  9.         }  

  10.     }</span>  

         利用hibernate的initialize()方法将这个代理对象给初始化

         注:在使用代理对象的getId()方法和getClass()方法的时候,并不会抛出不能初始化异常,因为这两个属性并不用查询数据库。

 

         二、在缺省的情况下,hibernate对于关联关系会采用懒加载的方式。也就是说1-1、1-N、N-1、N-N都存在懒加载的问题。

           2.1、one-to-one懒加载

         一对一的懒加载并不常用,因为懒加载的目的是为了减少与数据库的交互,从而提高执行效率,而在一对一关系中,主表中的每一条数据只对应从表的一条数据库,就算都查询也不会增加多少交互的成本,而且主表不能有contrained=true,所以主表是不能懒加载的。但是从表可以有。

         实现此种懒加载必须在从对象这边同时满足三个条件:
            1lazy=falselazy的属性有三个选项分别为:no-proxyfalseproxy
            2Constrained = true 
            3fetch=select
         注:当fetch设置为
join时,懒加载就会失效。因为fetch的作用是抓取方式,他有两个值分别问selectjoin,默认值为select。即在设为join时,他会直接将从表信息以join方式查询到而不是再次使用select查询,这样导致了懒加载的失效。

  

         2.2、one-to-many懒加载

         与one-to-one关联不同,对one-to-many而言,主表的每一条属性都会对应从表的多条数据,这个时候懒加载就显得非常有效了。比如一个部门里面有多个员工,如果没有懒加载,每查询这个部门的时候都会查询出多个员工,这会大大增加与数据库交互的成本。所以Hbernate默认的是加入懒加载的。这就是查询集合属性的时候返回的是一个PersistentIndexed*类型对象的原因。该对象其实就是一个代理对象。当然,可以在映射文件中通过将lazy属性设为假来禁用。

          Hibernate默认对one-to-many就是使用的懒加载,但用户也可以取消懒加载操作:
            一:设置lazy=”false”;
            二:设置fetch=”join”.
         实现此种懒加载必须在从对象这边同时满足两个个条件:
           1lazy=falselazy的属性有三个选项分别为:no-proxyfalseproxy
           2fetch=select

 

           2.3、mang-to-one懒加载

         此关联关系的懒加载和one-to-one的懒加载一样都是可要可不要的,因为对执行效率的提高都不是非常明显。虽然多对一与一对一关系方式相同,但是在Hibernate中多对一时,默认是进行懒加载的。另外有一点需要注意的是懒加载并不会区分集合属性里面是否有值,即使是没有值,他依然会使用懒加载

         实现此种懒加载必须在从对象这边同时满足两个个条件:
             1lazy=falselazy的属性有三个选项分别为:no-proxyfalseproxy
             2fetch=select

 

         2.4、many-to-many懒加载

         此关联关系的懒加载和one-to-many的懒加载一样对程序的执行效率的提高都是非常明显的。
         实现此种懒加载必须在从对象这边同时满足两个个条件:
            1lazy=falselazy的属性有三个选项分别为:no-proxyfalseproxy
             2fetch=select

         能够懒加载的对象都是被改过的代理对象,当相应的对象没有关闭时,访问这些懒加载对象的属性(getId和getClass除外)hibernate会初始化这些代理,或用hibernate.initalize(proxy)来初始化代理对象;当关闭session后在访问懒加载的对象就会出现异常

© 著作权归作者所有

共有 人打赏支持
xiaml
粉丝 2
博文 22
码字总数 15165
作品 0
西城
程序员
私信 提问
使用spring集成hibernate学习笔记

1.JDBC的自行车无法满足我们对复杂任务的需求 对持久化的复杂需求以下几点: a.懒加载(需要的时候进行加载) b.预先抓取(一个查询获取完整的关联对象) c.级联(更改数据库的同时修改其他表)...

ordiy
2016/08/07
27
0
Hibernate 笔记

1 failed to lazily initialize a collection of role: com.gmako.entity.UserInfo.extendsUserInfos, no session or session was closed 这是懒加载异常 配置文件设置lazy为false //主键ID......

sw3458856
2014/03/09
0
0
Hibernate懒加载

面试题: get、load方法区别? get: 及时加载,只要调用get方法立刻向数据库查询 load:默认使用懒加载,当用到数据的时候才向数据库查询。 懒加载:(lazy) 概念:当用到数据的时候才向数据库...

爪哇程序猿
2015/10/22
165
0
Hibernate之一级缓存和二级缓存

1:Hibernate的一级缓存:   1.1:使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率;(当执行一次查询操作的时候,执行第二次查询操作,先检查缓存中是否有...

别叫小伙
2017/03/21
0
0
Spring Boot中 hibernate懒加载(lazy loading)造成序列化失败

Spring Boot中 hibernate 延迟加载 | 懒加载(lazy loading)造成序列化失败 Spring hibernate 懒实例化 Spring Boot中 延迟加载 | 懒加载(lazy loading)造成序列化失败 问题描述 背景很简...

曹真
2017/08/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux虚拟机安装VmwareTool

1.点击虚拟机: 2.点击安装Vmware-Tools,出现如下界面,将圈起来的拖动到桌面 3.接着打开终端,执行解压缩命令 tar -xzv -f VMwareTools-10.2.5-8068393.tar.gz 这个后面的VMwareTools-10.2....

陈刚生
15分钟前
0
0
Java学习笔记(1) --JSE 、JEE、 JME三者的区别

java SE : java standard edition , JSE。它允许允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的java应用程序。 java SE包含了java Web 服务开发的类,并为java platform ,e...

hellation_
18分钟前
1
0
kafka 环境配置

https://www.cnblogs.com/fly-piglet/p/7762556.html

steel7c4
21分钟前
0
0
关于人工智能的思考

像人类一样可以思考,可以创造的人工智能会出现吗? 个人认为:会出现。但是出现的时间,取决了于硬件架构,和运算架构实现的时候。原因在于,人类智能可以出现,机器智能为什么不可以呢,不...

janl
23分钟前
0
0
破界!Omi生态omi-mp发布,用小程序开发生成Web

omi-mp 是什么 Omi 框架是微信支付线研发部和 AlloyTeam 开源的通用 Web 组件化框架,基于 Web Components,用来开发 PC、手机浏览器或者微信、手Q webview 的 Web 页面。自今年5月开源以来,...

腾讯开源
27分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部