Hibernate 懒加载
Lazy的概念就是只有在真正使用对象时,才会去创建。
对hibernate而言,就是真正加载时才发出加载Sql语句。 延迟加载机制是为了避免一些无谓的性能开销而提出来的。
重点牢记
1.Load支持延迟加载,get不支持延迟加载。
2.lazy的生命周期与session相同,lazy加载必须依赖于session一直开启。
3.Hibernate lazy属性,在3.x后是默认打开的,在以前版本中默认是关闭的。
4.hibernate通过cjlib实现代理。
先来看一个例子:
public class Classes {
private int id;
private String name;
private Set students;
// getter and setter..
}
private int id;
private String name;
private Set students;
// getter and setter..
}
public class Student {
private int id;
private String name;
// getter and setter..
}
private int id;
private String name;
// getter and setter..
}
其映射配置如下:
<hibernate-mapping>
<class name="hibernate.one2many.Classes" table="T_Classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" cascade="all" >
<key column="classid"/>
<one-to-many class="hibernate.one2many.Student"/>
</set>
</class>
<class name="hibernate.one2many.Student" table="T_Student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
<class name="hibernate.one2many.Classes" table="T_Classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" cascade="all" >
<key column="classid"/>
<one-to-many class="hibernate.one2many.Student"/>
</set>
</class>
<class name="hibernate.one2many.Student" table="T_Student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
在hibernate中,可以对类、普通属性、引用以及集合设置lazy属性,定义懒加载的特性。
Hibernate的懒加载,是通过在内存中对类、集合等的增强(即在内存中扩展类的特性[继承])来实现的,这些类通常称为代理类。
比如我们通过session.load(User.class,id)操作,加载一个对象的时候,hibernate返回的实际上是User的一个代理类实例(可通过IDE环境的debug模式运行程序,来观察其对象类型)。但如果通过session.get操作,则永远返回实际的对象实例(不是代理类实例),对上例而言,get操作永远返回User类的实例。
- Class级别的lazy属性设置
我们可以对class元素定义lazy属性,它可以取值为true/false,默认值是true。这意味着,我们在使用session.load操作的时候,hibernate并不会立刻发出SQL查询语句去从数据库中加载对象的属性数据,直到我们调用对象的某个方法以获取某些属性的时候(比如getXXX()),hibernate才会向数据库发出查询语句加载数据,这种延迟特性,就称为懒加载。(我们可以通过实际的例子来观察这种特性)
Class级别的lazy属性设置对整个类的所有属性起作用,控制的是其拥有的属性的懒加载特性(但如果其属性为集合或对另外一个实体对象的引用,则集合或引用的懒加载特性不受class的lazy设置的控制,也就是说,集合的数据或引用的实体对象的数据,仍然不会立刻加载!)
简单地来说,就是只对普通属性的延迟加载有效,不包括集合和其他类属性。
- Property的lazy属性设置
取值只有true/false。
需要类增强器来对实体类的Class文件进行强化处理。
在Hibernate3中,引入了一种新的特性——属性的延迟加载,这个机制又为获取高性能查询提供了有力的工具。比如它可以用于一个复杂对象中某个属性是一个大文本,我们不想再加载这个对象时浪费太多时间,那么我们就可以使用属性推后加载。
- 集合(collection)的lazy属性设置
在集合元素(如set)上,也可以设置lazy属性,它的意思是指定这个集合是否需要懒加载。集合上的lazy属性可以取值为:true/false/extra,默认值是true。- True,只有在调用集合(比如调用getStudents()方法)的时候,才会触发SQL查询
- False,取消懒加载特性,即在session.load方法的时候,就立刻发出相应的SQL查询,把集合数据查询出来
- Extra,是一种聪明的懒加载策略
- 在你调用getStudents()方法的时候,不会触发SQL查询
- 调用getStudents().size()方法的时候,会触发类似于:Hibernate: select count(id) from T_Student where classid =? 这样的SQL查询语句(这是一种很聪明的做法,如果lazy=”true”,getStudents().size()将会使得hibernate加载所有集合的数据到内存中)。
- 调用getStudents().contains()方法的时候(即判断是否包含某个对象),会触发类似于:select 1 from T_Student where classid =? and id =? 这样的SQL查询语句。
- 单端关联(One-to-one,many-to-one)的lazy属性设置
所谓单端关联,即一个对象有对另外一个对象的一个引用的时候(即many-to-one的情况)。
我们在many-to-one元素中,可以设置lazy属性,其取值为:false/proxy/no-proxy,默认值为proxy。
Proxy: 当前对象的单值相关对象只有在调用它的主键外的其他属性的get方法时才加载它。
No-proxy: 当前对象的单值相关对象在它的实体变量被访问的时候就被加载。