`

Hibernate查询之list/iterator

阅读更多

在Hibernate3中将Session.find(),Session.iterator()换成:session.createQuery().list(),session.creqteQuery().iterator(),(实现机制并没有什么区别);

两者都是根据指定条件查询并返回符合查询的条件的实体对象;

看下session.createQuery().list():

		List<TUser> users = session.createQuery(hql).list();
		int len = users.size();
		for (int i = 0; i < len; i++) {
			TUser user = users.get(i);
			System.out.println("User name:"+user.getName());
		}

在控制台上只会输出:

Hibernate: select   tuser0_.userid as userid0_, tuser0_.name as name0_,tuser0_.age as age0_, tuser0_.info as info0_  from t_user tuser0_  where   tuser0_.age>316  

显示的结果为:

User name:keith 299

 

在看下session.createQuery().iterate():

		Iterator it = session.createQuery(hql).iterate();
		while (it.hasNext()) {
			TUser users = (TUser) it.next();
			System.out.println("user Name:"+users.getName());
		}

 看下控制台上的输出:

Hibernate: select   tuser0_.userid as col_0_0_  from  t_user tuser0_ where   tuser0_.age>316
Hibernate: select   tuser0_.userid as userid0_0_,tuser0_.name as name0_0_, tuser0_.age as age0_0_,tuser0_.info as info0_0_   from    t_user tuser0_  where   tuser0_.userid=?

 所显示的结果为:

user Name:keith 299

 

两者相比较,list()只发一条语句将符合条件的数据全部查出,而iterator()却现将id查出来,然后根据id再将符合条件的数据查出,这就构成了N+1的问题;既然list更高效,为什么hibernate还将iterator存在呢?

 

这个问题与Hibernate缓存机制密切相关,我们将两种方法写在一起:

		List<TUser> users = session.createQuery(hql).list();
		int len = users.size();
		for (int i = 0; i < len; i++) {
			TUser user = users.get(i);
			System.out.println("user Name:"+user.getName());
		}
		
		System.out.println("\n query by list is Over,and query by iterator is start...");
		
		Iterator it = session.createQuery(hql).iterate();
		
		while (it.hasNext()) {
			TUser user = (TUser) it.next();
			System.out.println("users name:"+user.getName());
		}

 看下控制台的输出:

Hibernate: select  tuser0_.userid as userid0_,tuser0_.name as name0_,tuser0_.age as age0_,tuser0_.info as info0_   from   t_user tuser0_   where   tuser0_.age>316

user Name:keith 299

 query by list is Over,and query by iterator is start...

Hibernate: select  tuser0_.userid as col_0_0_  from  t_user tuser0_ where  tuser0_.age>316

users name:keith 299

 只是将之前的list()和iterator()放在一起使用,这时的iterator只执行了一条SQL;其中的差异在于hibernate的缓存机制;

list()方法将执行Select SQL从数据库中获取所有符合满足条件的记录并构造相应的实体对象,实体对象构建完毕后,就将其纳入缓存;

这样等到iterator()执行时,首先会执行一条SQL来查询符合条件数据的id,随即,iterator方法首先在本地缓存内根据id查找对应的实体对象是否存在,如果缓存中已经存在对应的数据,则直接以此数据对象作为查询结果;如果没有找到,则再次执行Select语句获得对应数据库中的表记录(如果iterator在数据库中查到并构建了完整的数据对象,也会将其纳入缓存中);

在上面这个实例中,list()将读取的数据放入缓存中,iterator()直接可以用于是出现了以上的结果;

 

当我们再次执行上面的程序,发现结果还是一样的;list()并没有去读取它自己放进缓存的数据,因为当我们list()查询完后,即使缓存中有一些符合条件的数据,但是我们也无法保证这些数据就是合法的,如果更改下条件,将大于316改成300;那么缓存中的数据只满足大于316不会满足大于300;所有list()方法还是需要执行一次Select SQL来保证结果的完整性;得出结论:list()实际上无法利用缓存,它对缓存只写不读,而iterator()可以充分利用缓存,如果目标数据只读或者读取相当频繁,可以使用iterator()来减少性能上的消耗;

 

但是会出现这样一个问题,如果是海量数据怎么办?如果超过10万条记录的话,会有很大的可能出发OutOfMemoryError;导致系统异常;那么就用iterator()和evict()来解决吧!将内存消耗保持在可以接受的范围内;比如:

		Iterator it = session.createQuery(hql).iterate();
		while (it.hasNext()) {
			TUser users = (TUser) it.next();
			//在一级缓存中清理
			session.evict(users);
			//在二级缓存中清理,二级缓存可以设定
			SessionFactory.evict(TUser.class, users.getUserid());
			System.out.println("user Name:"+users.getName());
		}

 但是这样的话,由于JVM的异步内存回收机制,无效对象会不断的在内存中积累等待回收,如果数据量很大,必然会频繁的激发JVM的内存回收机制,导致系统性能急剧下降。因此对于这样的问题,最好使用SQL或者存储过程!

分享到:
评论
2 楼 fddjxllren 2012-03-30  
session.find()是不支持动态绑定参数的.要使用iterator最好配合二级缓存的使用这样能减少N+1的出现率!!!要不然容易产生N+1的查询
1 楼 java_bigniu 2011-06-01  

相关推荐

    Hibernate教程24_Hibernate的补充_list与iterator

    http://blog.csdn.net/e421083458/article/details/8794127 该源码为Hibernate教程配套源码

    Hibernate中的query 分页.doc

    13. for (Iterator iter=userList.iterator(); iter.hasNext();) { 14. User user = (User)iter.next(); 15. System.out.println(user.getId()); 16. System.out.println(user.getName()); 17. } 18. session....

    hibernate二级缓存

    Hibernate二级缓存 在一个数据库系统中,如果缓存设置的... hibernate.cache.use_query_cache必须配置,如果想缓存使用findall()、list()、Iterator()、createCriteria()、 createQuery()等方法获得的数据结果集。

    Hibernate入门文档

    Hibernate 难点解析: hibernate中uuid和native的相关总结 ...hibernate二级缓存中list和iterator的用法 Hibernate中的对象有三种状态: lock和update区别 save 和update区别 update 和saveOrUpdate区别

    hibernate更新数据方法小结

    Session session=HibernateSessionFactory.getSession(); String sql=”from Usertable as user where user.username=?”; Query q=session.createQuery(sql); q.setString(0,username); List l=q.list(); Iterator...

    大数据量数据库优化.

    2) 对大数据量查询时,慎用list()或者iterator()返回查询结果, 3) 对于关联操作,Hibernate虽然可以表达复杂的数据关系 4) 对含有关联的PO(持久化对象)时 5) 在一对多、多对一的关系中,使用延迟加载机制,

    javaee三大框架整合宅急送项目lib包

    入库(点击左侧菜单入库) ----- Action (查询入库任务列表)---- instore_list.jsp ---- 办理任务 ---- instore_complete.jsp(提交form) --- Action (办理任务流转到下一个节点) 修改function 数据表 入库...

    低清版 大型门户网站是这样炼成的.pdf

    3.4.2 checkboxlist标签详解 137 3.4.3 combobox标签详解 138 3.4.4 doubleselect标签详解 139 3.4.5 file标签详解 141 3.4.6 form标签详解 142 3.4.7 hidden标签详解 143 3.4.8 select标签详解 143 3.4.9 ...

    Java常见面试题208道.docx

    116.hibernate 有几种查询方式? 117.hibernate 实体类可以被定义为 final 吗? 118.在 hibernate 中使用 Integer 和 int 做映射有什么区别? 119.hibernate 是如何工作的? 120.get()和 load()的区别? 121.说一下 ...

    Java学习笔记-个人整理的

    {4.7}集合的迭代(Iterator)}{85}{section.4.7} {4.8}Collections集合工具类}{86}{section.4.8} {4.9}Comparable与Comparator}{86}{section.4.9} {4.9.1}Comparable}{86}{subsection.4.9.1} {4.9.2}Comparator...

    深入浅出Struts2(附源码)

    6.12 iterator标签 107 6.13 append标签 110 6.14 merge标签 111 6.15 generator标签 113 6.16 sort标签 116 6.17 subset标签 118 6.18 小结 119 第7章类型转换 120 7.1 类型转换概述 120 7.2 类型转换错误...

    深入浅出Struts 2 .pdf(原书扫描版) part 1

    6.12 iterator标签 107 6.13 append标签 110 6.14 merge标签 111 6.15 generator标签 113 6.16 sort标签 116 6.17 subset标签 118 6.18 小结 119 第7章 类型转换 120 7.1 类型转换概述 120 7.2 类型转换错误消息的...

Global site tag (gtag.js) - Google Analytics