Hibernate iterate和list方法的区别

String hql = "from Student";
Query query = session.createQuery(hql);

 

对于这条语句的查询:

 

List<Student> stus = query.list();

会把所有的查询结果放到list中。一次加载到内存。

语句:select student0_.id as id3_, student0_.studentage as studentage3_, student0_.studentname as studentn3_3_ from Student student0_//当执行list方法的时候

 

Iterator<Student> stus = query.iterate();

该语句只把ID的值放到迭代器中,当遍历的时候,会根据ID的值再去数据库中查。并且该语句会产生N+1次查询。

语句1:select student0_.id as col_0_0_ from Student student0_ //当执行iterate方法的时候

语句2:select student0_.id as id3_0_, student0_.studentage as studentage3_0_, student0_.studentname as studentn3_3_0_ from Student student0_ where student0_.id=?//遍历获取值的时候

 

这两个方法各有千秋。请根据具体情况选择使用(牺牲内存或者牺牲网络资源)。

 

二、list和iterator

1 、list方法会直接直接到数据库中加载数据,然后将查询结果放入缓存中,当然如果你配置了查询缓存,他会先进入查询缓存寻找,如果没有满足条件的再进入数据库加载数据;

2、iterator方法在查询时是先从数据库中查询出所有满足条件的数据索引,然后再根据这些数据索引进入一级和二级缓存进行匹配,如果对于数据索引有实体对象则直接返回该对象,如果没有则在具体使用对象的时候才会进入数据库加载数据,并且把数据索引和对于实体对象放进缓存;

3、什么时候使用最合适呢?个人建议第一次查询使用list直接从数据库中读取所有数据,然后放到了缓存中,后面使用Iterator,直接从缓存中读取,利于提高性能;(你预期返回的结果在session,或二级缓存(second-level cache)中已经存在时)

 

 

 

三,实例演示:

实体对象的查询,查询的是实体对象的数据【重要】
  *n+1问题,在默认配置的情况下,使用query.iterate()操作,有可能有n+1问题,所谓n+1,指在查询对象数据的时候,发出了n+1条查询语句。
  1:首先发出了一条查询语句,查询对象的id列表
  n:在迭代访问每个对象的时候,如果缓存中没有对象数据,Hibernate会在此发出一条查询语句,
     查询相应的对象 
  
  *List操作与Iterate操作的区别
   list,每次都会发出一条查询语句,查询所有的对象
   iterate,首先发出一条查询语句,查询对象的id列表,然后根据缓存情况,决定
    是否发出更多的查询语句,来查询对象数据

 

package com.bjsxt.hibernate;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import junit.framework.TestCase;

/**
 * 对象查询中的list操作和iterator操作的差异
 * @author Administrator
 *
 */
public class SimpleObjectQueryTest2 extends TestCase {
	
	public void testQueryWithListMethod() {
			Session session = null;
			try {
				session = HibernateUtils.getSession();
				
				/**
				 * 将发出一条查询语句,获取Student的集合数据
				 * select student0_.id as id1_, student0_.name as name1_, 
				 * student0_.createTime as createTime1_, student0_.classid as classid1_ 
				 * from t_student student0_
				 */
				List students = session.createQuery("from Student").list();
				for (Iterator iter = students.iterator();iter.hasNext();) {
					Student student = (Student)iter.next();
					System.out.println(student.getName());
				}
			}catch(Exception e) {
				e.printStackTrace();
			}finally {
				HibernateUtils.closeSession(session);
			}	
		}		
	
	public void testQueryWithIterateMethod() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//先发出查询id的列表语句
			//select student0_.id as col_0_0_ from t_student student0_
			//再依次发出查询对象的sql(根据id)
			//select student0_.id as id1_0_, student0_.name as name1_0_, 
			//student0_.createTime as createTime1_0_, student0_.classid as classid1_0_ 
			//from t_student student0_ where student0_.id=?
			Query query = session.createQuery("from Student");
			Iterator students = query.iterate();
			while (students.hasNext()) {
				Student student = (Student)students.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}	
	
	public void testQueryWithListAndIterate() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Query query = session.createQuery("from Student");
			List students = query.list();
			for (Iterator iter = students.iterator();iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
			
			//如果使用iterate进行查询
			//因为list操作已经将对象加载到了session的一级缓存,所以
			//再使用iterate操作的时候,它先会发出查询id列表的查询语句
			//再根据id到缓存中获取相关的数据
			//只有再缓存中找不到相关数据的情况下,才会再次发出sql进行查询
			Iterator studentsIter = query.iterate();
			while (studentsIter.hasNext()) {
				Student student = (Student)studentsIter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
		
	}
	
	public void testQueryWithListAndList() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Query query = session.createQuery("from Student");
			List students = query.list();
			for (Iterator iter = students.iterator();iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
			
			//再次发出sql
			//在默认情况下,list每次都会向数据库发出查询对象数据的sql,
			//除非配置了查询缓存,所以下面的list()操作,虽然在session已经有了
			//对象缓存数据,但list()并不理会这个中缓存,而再次发出查询语句进行查询
			students = query.list();
			for (Iterator iter = students.iterator();iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	
}

 

你可能感兴趣的:(Hibernate)