【Hibernate】lazy延迟加载

     延迟加载(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>没有影响。




展开阅读全文

没有更多推荐了,返回首页