首页 > 学院 > 开发设计 > 正文

【Hibernate】lazy延迟加载

2019-11-10 17:52:00
字体:
来源:转载
供稿:网友

     延迟加载(lazy load)是(也称为懒加载)Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。

    hibernate的lazy策略可以使用在如下四个场景:

    * <class>标签上,可以取值:“true/false”

    * <PRoperty>标签上,可以取值:“true/false”,但是需要类增强工具配合使用,不常用。

    * <set>/<list>标签上,可以取值:“true/false/extra”,对集合的延迟加载很常用。

    * <many-to-one>/<one-to-one>单端关联标签上,可以取值"false/proxy/noproxy"

    最常使用的地方就是在<set>/<list>集合上。

    一个Demo

public void testQuery1(){	session session = null;	try{		session = HibernateUtils.getSession();		session.beginTransaction();		//查询操作,不会发出sql		User user = (User)session.load(User.class, 1);				//显示id--(代理操作)		System.out.println("user.id=" + user.getId());		//显示name -- (数据库开始查询操作)		System.out.println("user.name=" + user.getName());				System.out.println("user.passWord=" + user.getPassword());		session.getTransaction().commit();	}catch(Exception e){		e.printStackTrace();			}finally{		HibernateUtils.closeSession(session);	}}        这个例子中:  (1)因为load默认支持lazy加载,执行session.load之后,打印user.getId();因为传入的id,且通过代理操作,并未进行数据库查询,在打印user.getName()时,开始进行查询操作。  (2)如果Name属性支持lazy(在hbm.xml中将该属性设置为lazy加载),执行到"user.getName()"的时候,才会把Name值加载出来。

     

   现在修改这个Demo:

public void testQuery2(){	Session session = null;	User user = null;	try{		session = HibernateUtils.getSession();		session.beginTransaction();				user = (User)session.load(User.class, 1);		session.getTransaction().commit();			}catch(Exception e){		e.printStackTrace();			}finally{		HibernateUtils.closeSession(session);		//放在session关闭之后		System.out.println("user.name=" + user.getName());	}		}            将user.getName()方法写到了closeSession之后,报出SessionException的错误,可见,hibernate中使用lazy策略,必须放到session当中。

    对Collection集合中的“lazy”策略

    通过一个Load的Demo

public void testLoad1(){	Session session = null;	try{		session = HibernateUtils.getSession();		session.beginTransaction();		//(1)		Classes classes = (Classes)session.load(Classes.class, 1);		//(2)		System.out.println("Classes.name=" + classes.getName());		//(3)		Set students = classes.getStudents();		//(4)		for(Iterator iter=students.iterator(); iter.hasNext();){			Student student = (Student)iter.next();			System.out.println("student.name=" + student.getName());		}		session.getTransaction().commit();	}catch(Exception e){		e.printStackTrace();		session.getTransaction().rollback();	}finally{		HibernateUtils.closeSession(session);	}}          如上,代码中标记了(1)(2)(3)(4)共计4条测试语句,默认的hbm.xml配置中,对<set>的lazy形式也是“true”,当调用testLoad1()的时候,

    不会发出sql的有:(1)(3)

    会发出Sql的有:(2)(4)

    做到了,真正的 只有在使用的时候,才会加载,即体现出lazy加载的一个好处。

    然而对于lazy="true"有一个影响效率性能的地方,参考这个demo:

public void testLoad2(){	Session session = null;	try{		session = HibernateUtils.getSession();		session.beginTransaction();		//不会发出sql		Classes classes = (Classes)session.load(Classes.class, 1);		//会发出sql		System.out.println("Classes.name=" + classes.getName());		//不会发出sql		Set students = classes.getStudents();		//会发出查询该班级全部学生的sql语句,存在效率问题		System.out.println("count=" + students.size());				session.getTransaction().commit();	}catch(Exception e){		e.printStackTrace();		session.getTransaction().rollback();	}finally{		HibernateUtils.closeSession(session);	}}           将for循环替换为查询students.size();使用lazy="true"策略,加载过程中,对size的查询虽然支持lazy,但是发出的sql语句是select * from t_table,改善如下:    将lazy="true"修改为lazy="extra",此时发出的sql语句为"select count(*) from t_table",提升了效率,同时extra继承了true的所有优点,对<set>最好使用lazy="extra",当然使用lazy="false",肯定就不支持集合的延迟加载了。

    附注:<class>上的lazy策略,影响的仅仅是<property>这类普通属性,对于<set>/<list>没有影响。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表