出自圣思院hibernate14讲 [Query接口的list与iterator方法深度解析与延迟加载详析]
Query query=session.createQuery("from User");
Iterator<User> iter=query.iterate();
while(iter.hasNext()){
System.out.println(iter.next());
}
以上代码在运行时, 会出现一个有意思的现象 ,就是程序像数据库发送了N条select语句。(跟数据库里存在的数据量一样)
附上console的内容:
Hibernate: select user0_.id as col_0_0_ from test_user user0_
Hibernate: select user0_.id as id1_1_0_, user0_.test_name as test2_1_0_ from test_user user0_ where user0_.id=?
com.lj.zhang.User@4406cef4
Hibernate: select user0_.id as id1_1_0_, user0_.test_name as test2_1_0_ from test_user user0_ where user0_.id=?
com.lj.zhang.User@1d716fa0
这里先看一下doc里面对iterate的说明
Iterator iterate() throws HibernateException
Return the query results as an Iterator. If the query contains multiple results pre row, the results are returned in an instance of Object[].
Entities returned as results are initialized on demand. The first SQL query returns identifiers only.
Returns:
the result iterator
也就是说, 返回的对象是按需初始化, 第一个sql查询只返回identifiers,在这里就是ID。
Hibernate: select user0_.
id as col_0_0_ from test_user user0_
这句被执行的地方在
Iterator<User> iter=query.iterate();
---------再看一下最常用的list方法说明
Return the query results as a List. If the query contains multiple results pre row, the results are returned in an instance of Object[].
这里获取的row就直接被封装到Object[]里面,然后返回。
用一个删除的例子来说明两者的区别.
Query query = session.createQuery("from User");
Iterator<User> iter = query.iterate();
while (iter.hasNext())
{
session.delete(iter.next());
}
这个例子会产生大量的select语句, 因为每次执行delete的时候, 都要从数据库读取一个对象。
而换成
List<User> list=query.list();
Iterator listIter=list.iterator();
while(listIter.hasNext()){
session.delete(listIter.next());
}
就只会产生一个select语句, 这样就节约了开支。
----------再用一个读取的例子看一下-------------
Session session = HibernateUtil.openSession();
Transaction tx = null;
tx = session.beginTransaction();
Query query = session.createQuery("from User");
List<User> list=query.list();
// Iterator it=query.iterate();
tx.commit();
[b]session.close();[/b]
for(User u:list){
System.out.println(u.getName());
}
// while(it.hasNext()){
// System.out.println(((User)it.next()).getName());
// }
这里加入了session.close(),
通过list()方法会正常运行。
但是iterator() 方法就会出错, 因为session已经被关闭。而iterator在被调用的时候则需要再次发送sql语句, 但是已经找不到session了。
=============总结=============
Query接口的list()方法和iterator()方法都可以实现获取查询的对象, 但是list()方法返回的每个对象都是完整的(对象中的每个属性都被表中的字段填充上了), 而iterator()方法所返回的对象中仅包含了主键值(标识符), 只有对iterator()中的对象进行操作时, hibernate才会向数据库再次发生SQL语句来获取该对象的属性值。