hibernate Query.list() 与 Query.iterator() 区别

iterator()方法的出现主要是为了解决查询是的性能问题。例如下面使用list()方法取得对象的代码:

........//打开Session,开启事务

Queryq=session.createQuery("fromStudent");

//以下为查询在name中"t"字符的所以学生

q=session.createQuery("fromStudentswheres.namelike't%'");

q.list();

........//提交事务,关闭session

运行以上代码,得到的控制台信息如下:

Hibernate:selects.*fromstudents

Hibernate:selects.*fromstudentswheres.namelike't%'

第2条select语句查找所以匹配条件的对象,然后根据起id值到Session缓寸中查找这个对象是否已经存在,如果已经存在,则返回缓存中这个对象的引用,不再重新组装对象。因此select*是不必要的,只需要selects.id即可。

Query接口的iterator()方法发送select语句检索id字段,然后根据id值在Session缓存和二级缓存中查找匹配的对象,如果存在,把它直接加到查询结果返回,如果不存在,根据刚才已经检索出来的id,执行额外的select语句到数据库检索该对象。

Student表中共有两个Student对象,首先通过get()方法把一个Student对象加载到Session缓存,然后再查询所有的Student对象,观察控制台的输出语句,如下代码所示:

.....//打开session,开启事务

stu = (Student) session.get(Student.class , new Integer(1));
Query q = session.createQuery("from Studnet");

Iteratorit=q.iterator();

stu1=(Student)it.next();

stu2=(Student)it.next();

........//提交事务,关闭session

运行以上代码,得到的控制台信息如下:

Hibernate:selects.*fromstudentswheres.id=?

Hibernate:selects.idfromstudents

Hibernate:selects.*fromstudentswheres.id=?

第1条select*语句是由get()方法引起的,第2条selects.id是由q.iterator()引起的(如果调用集合对象的iterator()方法,将会发送select*fromtable,比如team.getStudent().iterator()),第3条语句是因为在缓存中只存在一个Student对象,还有一个Student对象必须发送SQL语句从数据库取得,然后再把它加入到session缓存中。

  Query接口的iterator()方法和load()方法很相似,只不过load()用于加载单独的对象,而iterator()用于批量的加载。某 些情况下, 可以使用iterator()获得更好的性能。这通常用于预期返回的结果在Session,或二级缓存中(second-level cache)中已经存在时的情况。当缓存中的对象很少,或者iterator()查询的范围过于宽广时(比如HQL语句"from Student"),反而对性能造成不利的影响,因为iterator()方法第一次总是查询所有的id,然后根据id值一条一条地发送select 语句去取得对象,因此如果有有10000条记录,而且是在Session中是第一次查询时(缓存中还没有对象数据),则要发送10001条SQL语句去取 得数据,这样的话,还不如直接用以下语句来得方便高效。 
PS:以上资料 来源于Hibernate 开发及整合应用大全 --蔡雪焘 编著

相关推荐