一.延迟加载的概念html
当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的状况下)获取到的也是代理对象,因此在上面这几种场景下就是延迟加载。sql
二.理解当即加载的概念数据库
当Hibernate从数据库中加载某个对象时,加载关联的对象,生成的实际对象,获取使用session中的get的方法获取到的是实际对象。session
三.为何要使用延迟加载性能
延迟加载策略能避免加载应用程序不须要访问的关联对象,以提升应用程序的性能。.net
四.当即加载的缺点代理
Hibernate在查询某个对象时,当即查询与之关联的对象,咱们能够看出这种加载策略存在两大不足:xml
1.select的语句数目太多,须要频繁的访问数据库,会影响查询的性能。htm
2.在应用程序只须要访问要的对象,而不须要访问与他关联的对象的场景下,加载与之关联的对象彻底是多余的操做,这些多余的操做是会占内存,这就形成了内存空间的浪费。对象
五.何时使用延迟加载何时使用当即加载
若是程序加载一个持久化对象的目的是为访问他的属性,则能够采用当即加载。若是程序加载一个持久化对象的目的仅仅是为了得到他的引用,则能够采用延迟加载。
六.Hibernate在对象-关系映射问价中配置加载策略
I.类级别:
<class>元素中lazy属性的可选值为true(延迟加载)和false(当即加载);
<class>元素中的lazy属性的默认值为true
II.一对多关联级别:
<set>元素中的lazy属性的可选值为:true(延迟加载),extra(加强延迟加载)和false(当即加载);
<set>元素中的lazy属性的默认值为true
III.多对一关联级别:
<many-to-one>元素中lazy属性的可选值为:proxy(延迟加载),no-proxy(无代理延迟加载)和false(当即加载)
<many-to-one>元素中的lazy属性的默认值为proxy
在下面的一些案例中都会以员工(Emp)的部门(Dept)的例子讲解:
员工和部门是多对一的关系:
关于员工和部门的Hibernate配置就不啰嗦了:能够看个人这篇博客:http://www.cnblogs.com/heyongjun1997/p/5767187.html
I.1类级别的查询策略:
01.当即加载案例:
需求:经过Session的load()方法加载Dept对象时:
首先在Dept.hbm.xml文件中配置lazy属性为false,表示当即加载。
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 若是经过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); // 关闭session HibernateUtil.closeSession(); }
咱们知道使用Load方法加载的是代理对象,只会在属性里保存一个OID,可是若是在Dept映射文件中配置了类级别的lazy为false就表明加载该对象时当即加载,也就是当即检索一道数据库,发出sql:
02.延迟加载案例:
一样是获取Dept对象,可是要把Dept.hbm.xml配置文件的类级别的lazy属性改成lazy=”true” 或者不写,应为类级别的lazy属性默认就是true,
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 若是经过load方式加载Dept对象 session.load(Dept.class, 12); // 关闭session HibernateUtil.closeSession(); }
此时Dept.hbm.xml配置文件的类级别的lazy属性为true,则是延迟加载,那么load方法获取的知识Dept的代理对象,因此他不会去检索数据库。
II.1一对多和多对多关联的查询策略
01.当即加载案例:
在获取部门对象的时候同时获取员工对象:
设置Dept.hbm.xml 类级别的lazy属性为false;表示当即加载:
设置<set>元素的lazy属性为false,表示在加载部门的同时当即加载员工:
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 若是经过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); // 关闭session HibernateUtil.closeSession(); }
控制台输出结果:
当你想获取一的一方(Dept)的对象同时,你也要加载多的一方(Emp)的对象,那么你要在一的一方(Emp)的<set>的节点上加上lazy="false"表示当即加载,因此在使用Load方式加载Dept对象的时候,Emp对象也会不加载出来,因此程序在运行到Dept dept=(Dept)session.load(Dept.class, 12);会发出两条sql语句:
第一条是查询部门的信息,第二条sql是根据部门编号去数据库中检索员工信息。
02.延迟加载:
若是把上面的案例<set>节点的属性lazy改成trur,或者默认不写,那么在加载Dept对象的时候,就不会再去加载Emp对象,并且只会发出一条sql,这条sql就是指检索部门的信息。
03.加强延迟加载:
当<set>元素中配置lazy的属性为extra,代表是加强延迟加载策略。
其实加强延迟加载策略与通常的延迟加载策略lazy="true"很是类似。他们主要区别在于,咱们看到这个名词加强延迟加载,顾名思义就是这个策略能在进一步的帮我延迟加载这个对象,也就是代理对象的初始化时机。
演示案例:
01. 当set节点的lazy属性为true,或者不写的话(取默认值),那么执行如下语句:
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 若是经过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); //拿该部门下的员工的人数:也就是集合的大小 dept.getEmps().size(); // 关闭session HibernateUtil.closeSession(); }
输出结果:
02. 当set节点的lazy属性为extra那么执行如下语句:
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 若是经过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); //拿该部门下的员工的人数:也就是集合的大小 dept.getEmps().size(); // 关闭session HibernateUtil.closeSession(); }
输出结果:
III.1多对一关联的查询策略
在映射文件中,<many-to-one>元素用来设置多对一的关系,在Emp.hbm.xml文件中代表Emp类到Dept类的多对一的关联关系:
01.延迟加载
需求:获取Emp对象,可是并不去加载与之关联的Dept对象。
首先要设置<many-to-one>节点的lazy属性为proxy,表示延迟加载。
@Test
public void loadEmp() {
// 获取Session对象
Session session = HibernateUtil.currentSession();
// 若是经过load方式加载Dept对象
Emp emp=(Emp)session.get(Emp.class, 1);
//获取Dept对象,由于此时的配置文件lazy是proxy,因此是代理对象
Dept dept=emp.getDept();
// 关闭session
HibernateUtil.closeSession();
}
控制台输出结果:
结果你们可想而知:<many-to-one>节点的lazy属性为proxy,表示延迟加载。在加载Emp对象的时候会发出sql去查询数据库,可是在获取Dept对象的时候延迟加载了,因此不会发出sql。
02.无代理延迟加载:
在<many-to-one>元素中配置lazy属性为no-proxy,表示无代理延迟加载。
@Test public void loadEmp() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 若是经过load方式加载Dept对象 Emp emp=(Emp)session.get(Emp.class, 1); //获取Dept对象,由于此时的配置文件lazy是proxy,因此是代理对象 Dept dept=emp.getDept(); // 关闭session HibernateUtil.closeSession(); }
此程序在加载的Emp对象dept属性为NULL,当程序运行到第3行的时候将触发Hibernate执行查询Dept表的select语句,,从而加载Dept对象,因而可知,当lazy属性为proxy时,能够延长延迟加载Dept代理对象的时间,而lazy属性为no-proxy时,则能够避免使用由Hibernate提供的Dept代理类实例,是Hibernate对程序提供更加透明的持久化服务。
03.当即加载:
首先要设置<many-to-one>节点的lazy属性为false,表示当即加载。
@Test
public void loadEmp() {
// 获取Session对象
Session session = HibernateUtil.currentSession();
// 若是经过load方式加载Dept对象
Emp emp=(Emp)session.get(Emp.class, 1);
//获取Dept对象,由于此时的配置文件lazy是false,因此是实际对象
Dept dept=emp.getDept();
// 关闭session
HibernateUtil.closeSession();
}
控制台输出结果: