hibernate延迟加载

来源:互联网 发布:mac 盟军敢死队中文版 编辑:程序博客网 时间:2024/06/15 17:35

至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适,

因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,

我们让数据在需要的时候才进行加载,这时我们就用到了懒加载。

Hibernate的延迟加载一共有三种类型:

1、实体延迟加载

在HIBERNATE中利用代理类来实现对实体的延迟加载,只有在调用实体的属性时,才会调用代理类来加载实体数据。

2、集合延迟加载

在一对多映射中,例如一个用户有多个邮箱例子中。我们可以对邮箱集合属性做延迟加载处理,因为查询用户数据时,并不一定都要查询邮   箱,只有在需要使用邮箱时才从数据库查询出来,这样可以大大提高系统性能。

3、属性延迟加载

在实际项目开发中 我们经常会遇到大数据如BLOB数据 如文章,但这些数据我们并不经常要用到,这时我们可以对这些属性采用 延迟加载,属  性延迟加载只有在要使用到延迟加载的属性时,才从数据库查询出属性。可以大大提高系统性能。

比如部门ENTITY和员工ENTITY,部门与员工1对多,如果lazy设置为 false,那么只要加载了一个部门的po,就会根据一对多配置的关系把所有员工的po也加载出来。但是实际上有时候只是需要用到部门的信息,不需要用到 员工的信息,这时员工po的加载就等于浪费资源。如果lazy设置为true,那么只有当你访问部门po的员工信息时候才回去加载员工的po的信息。

在Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在Hibernate3中还提供了对属性的延迟加载。


通过将class的lazy属性设置为true,来开启实体的延迟加载特性。

如果我们运行下面的代码:
User user=(User)session.load(User.class,"1");(1)   
System.out.println(user.getName());                 (2) 


当运行到(1)处时,Hibernate并没有发起对数据的查询,如果我们此时通过一些调试工具(比如Eclipse的Debug工具),观察此时user对象的内存快照,我们会惊奇的发现,此时返回的可能是User$EnhancerByCGLIB$$bede8986类型的对象,而且其属性为null,这是怎么回事?session.load()方法会返回实体对象的代理类对象,这里所返回的对象类型就是User对象的代理类对象。在Hibernate中通过使用CGLIB,来实现动态构造一个目标对象的代理类对象,并且在代理类对象中包含目标对象的所有属性和方法,而且所有属性均被赋值为null。通过调试器显示的内存快照,我们可以看出此时真正的User对象,是包含在代理对象的CGLIB$CALBACK_0.target属性中,

当代码运行到(2)处时,此时调用user.getName()方法,这时通过CGLIB赋予的回调机制,实际上调用CGLIB$CALBACK_0.getName()方法,当调用该方法时,Hibernate会首先检查CGLIB$CALBACK_0.target属性是否为null,如果不为空,则调用目标对象的getName方法,如果为空,则会发起数据库查询,生成类似这样的SQL语句:select * from user where id=’1’;来查询数据,并构造目标对象,并且将它赋值到CGLIB$CALBACK_0.target属性中。 这样,通过一个中间代理对象,Hibernate实现了实体的延迟加载,只有当用户真正发起获得实体对象属性的动作时,才真正会发起数据库查询操作。所以实体的延迟加载是用通过中间代理类完成的,所以只有session.load()方法才会利用实体延迟加载,因为只有session.load()方法才会返回实体类的代理类对象。


0 0
原创粉丝点击