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); } } }