hibernate的list和iterate的区别
一、先介绍一下java中的缓存系统JCS(java cache system)
1、JCS(Java Caching System)是一个对象Cache,它可以把Java对象缓存起来,提高那些访问频率很高的Java对象的存取效率。JCS是按照对象的唯一标示来存取对象的,比如说可以按照对象的 hashCode来存取。
2、对于Hibernate来说,可以利用JCS来缓存查询结果,这样当下次访问同样的数据,就无须去数据库取,直接从JCS中取出来,加快了查询速度。
3、当Hibernate使用List或者Iterator方式来第一次读取数据的时候,JCS是空的,此时不管是List方式还是Iterator方式都会往JCS里面填充查询出来的持久对象,
例如: select c from Cat as c
而 select c.id, c.name from Cat as c 这种HQL语句不构造PO,因此不会去填充JCS。
4、从JCS中区数据:
从JCS中取数据是按照对象的唯一标示来存取的,而对于PO持久对象来说,唯一标示就是主键,因此Hibernate首先必须获得主键列表,然后根据主键列表挨个判定,看这个持久对象究竟是在JCS里面还是在数据库里面,假如在JCS里面,那么按照主键取,假如在数据库,那么发送sql取。
5、这里先介绍一下Iterator可以使用JCS,而List不能。上面说了,用JCS之前,要先获得持久对象的主键,才能去JCS里面取持久对象,而获得主键列表必须去数据库中取得,这一步是没有办法缓冲的。
二、list和iterate查询数据不同形式:
1、Hibernate Iterator的查询本身是分为两步的:存在N+1问题
==> select id from cat //一条
==> select * from cat where id = ? //n条
解析:第一步,去数据库中取主键列表,第二步,按照主键一个一个取数据。假如不用JCS的话,那么从数据库中取出n条记录就需要n+1次sql查询,假如使用了JCS,他会先到JCS里面去看看,按照主键去找持久对象,假如有了,直接拿出来用,假如没有,那么只好去数据库中取得,然后再把它填到JCS里面去。
2、而Hibernate List方式:
==> select * from cat
它是JDBC的简单封装,一次sql就把所有的数据都取出来了,它不会像Iterator那样先取主键,然后再取数据,因此List无法利用JCS。不过List也可以把从数据库中取出的数据填充到JCS里面去。当再次使用list查询数据的时候,仍然要发送sql去数据库中读取数据,证明list()方法不使用缓存
三、list和iterate返回的对象分析:
list()中返回的是实体对象, 而iterate()中返回的对象是代理对象.
转载:http://blog.csdn.net/liumuqi110/article/details/4625055
四、list和iterate对缓存的使用情况
1、iterate会查询session缓存、2级缓存, list只会使用查询缓存(如果查询缓存开启的话)
2、当查询缓存开启时,对iterate和list查询语句的影响
查询缓存:将query 的cache打开的话,缓存的是query本身,以hql 生成的 sql ,再加上参数,分页等信息做为key值, 而不是query的结果.query的结果是放在session的cache中和二 级cache中,和query的cache是有区别的.
配置查询缓存:打开query的cache:1,在config中设置 hibernate.cache.use_query_cache = true,2,在创建query后query.setCacheable(true);
下面是打开query的cache后用list 的几个场景:
1:
Query q1 = s1.createQuery("from com.test.hb.Hbtest h where h.id<3");
q1.setCacheable(true);
Query q2 = s1.createQuery("from com.test.hb.Hbtest h where h.id=1");
q2.setCacheable(true);
从逻辑上将,第一个query查询出的值应该包含第二个query,但是第二个query不会用query的cache,而是会从新查询数据库.
2:
Query q1 = s1.createQuery("from com.test.hb.Hbtest h where h.id=1");
q1.setCacheable(true);
Query q2 = s1.createQuery("from com.test.hb.Hbtest h where h.id=1");
q2.setCacheable(true);
两个query一模一样,第二个query会用query的cache,不会从新查询数据库.
3:
Query q1 = s1.createQuery("from com.test.hb.Hbtest h where h.id=?").setInteger(0, 1);
q1.setCacheable(true);
Query q2 = s1.createQuery("from com.test.hb.Hbtest h where h.id=?").setInteger(0, 1);
q2.setCacheable(true);
两个query是一样的,第二个query会用query的cache,不会从新查询数据库.
4,
Query q1 = s1.createQuery("from com.test.hb.Hbtest h where h.id=?").setInteger(0, 1);
q1.setCacheable(true);
Query q2 = s1.createQuery("from com.test.hb.Hbtest h where h.id=?").setInteger(0, 2);
q2.setCacheable(true);
从逻辑上将,两个query是不一样的,第二个query不会用query的cache,而是会从新查询数据库.
query的cache打开后用iterator 的场景:
query的cache不会缓存第一次针对ID的SQL,后面iterator的时候,会根据session中的cache决定数据库的访问.可以说query的cache对iterator方式没有影响.
**如果cache的是native SQL,两个query的sql 语句必须是一样的(包括大小写).如下面的例子会访问两次数据库.
本地sql:
Query q1 = s1.createSQLQuery("select val from Hbtest H where H.id=1");
Query q2 = s1.createSQLQuery("select val from Hbtest h where h.id=1");
而对于HQL则不会,HQL会被hibernate翻译成SQL,在这过程会'识别'出是不是相同的SQL.下面的例子只访问1次数据库.
Query q1 = s1.createQuery("from com.test.hb.Hbtest h1 where h1.id=1");
Query q2 = s1.createQuery("from com.test.hb.Hbtest h where h.id=1");
五、iterate和list的使用情况:
iterate:
s1 = sessionFactory.openSession();
Query q = s1.createQuery("from com.test.hb.Hbtest h where h.id<2");
Iterator itr = q.Iterator();
while(itr.hasNext()){
Hbtest tbo = (Hbtest)itr.next();
}
list:
iterate:
s2 = sessionFactory.openSession();
Query q = s2.createQuery("from com.test.hb.Hbtest h where h.id<2");
List ls = q.list();
int i=0;
while(i<ls。size()){
Hbtest tbo = (Hbtest)ls。get(i);
i++;
}
两者相结合的使用形式:
s1 = sessionFactory.openSession();
Query q = s1.createQuery("from com.test.hb.Hbtest h where h.id<2");
List l = q.list();
Iterator itr = l.iterator();
while(itr.hasNext()){
Hbtest tbo = (Hbtest)itr.next();
}
list()方法会一次取出所有的结果集对象,而且他会依据查询的结果初始化所有的结果集对象。如果在结果集非常庞大的时候会占据非常多的内存,甚至会造成内存溢出的情况发生。
iterator()方法在执行时不会一次初始化所有的对象,而是根据对结果集的访问情况来初始化对象。一次在访问中可以控制缓存中对象的数量,以避免占用过多的缓存,导致内存溢出情况的发生。
原文链接:http://www.linuxidc.com/Linux/2012-01/52003.htm
hibernate的list和iterate的区别的更多相关文章
- hibernate中@Entity和@Table的区别
Java Persistence API定义了一种定义,可以将常规的普通Java对象(有时被称作POJO)映射到数据库.这些普通Java对象被称作Entity Bean.除了是用Java Persis ...
- JavaWeb_(Hibernate框架)Hibernate与c3p0与Dbutils的区别
JavaWeb_(Hibernate框架)使用Hibernate开发用户注册功能 传送门 JavaWeb_(Hibernate框架)使用c3p0与Dbutils开发用户注册功能 传送门 Hiberna ...
- 分享知识-快乐自己:Hibernate中的 quert.list() 与 quert.iterate() 方法区别
区别如下: quert.list() : 1):每次都是通过一条语句直接操作数据库取出所有的数据返回(并且将对象存入hibernate缓存中): 2):不会从一二级缓存中查询数据: 3):之执行一条S ...
- Hibernate - list()和iterate()的区别
list()和iterate()都可以用来获得Query取得的HQL结果list()使用的是即时加载.查询时会之前去数据库查询HQL并将所有结果存在缓存中.iterate()使用的是延时加载.查询时只 ...
- hibernate的集中持久化方法的区别
一.预备知识 在所有之前,说明一下,对于hibernate,它的对象有三种状态,transient.persistent.detached 下边是常见的翻译办法: transient:瞬态或者自由态 ...
- Hibernate的save()和persist()的区别
hibernate之所以提供与save()功能几乎完全类似的persist()方法,一方面是为了照顾JPA的用法习惯.另一方面,save()和 persist()方法还有一个区别:使用 save() ...
- hibernate延迟加载(get和load的区别)
概要: 在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一 ...
- hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等
hibernate的保存hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别:一.预备知识:在所有之前,说明一下,对于hibernate,它的对象有三种状态,t ...
- Hibernate中openSession() 与 getCurrentSession()的区别
1 getCurrentSession创建的session会和绑定到当前线程,而openSession每次创建新的session. 2 getCurrentSession创建的线程会在事务回滚或事物提 ...
随机推荐
- 单元测试框架unittest,ddt
unittest case.py 测试用例 suite.py 测试套件 loader.py 加载测试用例 run.py 执行测试用例 result.py 测试结果,测试报告 main mock 模拟测 ...
- vue2.0过度动画
vue在插入.更新或移除dom时,提供了多种不同方式的应用过度效果. 包括以下工具: 在css过渡和动画中自动应用class. 可以配合使用第三方css动画库,如animate.css 在过渡钩子函数 ...
- require和require_once经济性能对比
require和require_once都是PHP函数,开发人员可以使用它们在某个特定的脚本中导入外部PHP文件.你可以根据应用程序的复杂度调用一次或若干次require_once/require.使 ...
- 《大型网站系统与JAVA中间件实践》读书笔记-消息中间件
消息中间件 1.消息中间件的价值 1.1 透过示例看消息中间件对应用的解耦 1.1.1.通过服务调用让其他系统感知事件发生的方式 假设我们要做一个用户登录系统,其中需要支持的一个功能是,用户登录成功 ...
- Linux设置中文语言的一种方式
刚开始接触Linux时,如果对于英语不太好的人来说,看到英语的系统时就有点头晕. 能把Linux系统设置为中文就变得急需了. 有一个最简单的方法就是,在登录时,下面就有一个选择语言的选项. 如图:
- Java中的赋值运算符
赋值运算符是指为变量或常量指定数值的符号.如可以使用 “=” 将右边的表达式结果赋给左边的操作数. Java 支持的常用赋值运算符,如下表所示: public class HelloWorld{ pu ...
- Pandas数据结构
Pandas处理以下三个数据结构 - 系列(Series) 数据帧(DataFrame) 面板(Panel) 这些数据结构构建在Numpy数组之上,这意味着它们很快. 维数和描述 考虑这些数据结构的最 ...
- Mine_hibernate
1. __z知识点\整理_归纳 ==> "ZC_归纳.txt" 和 "ZC_归纳__12_用Eclipse开发hibernate.txt" 2.
- CodeForces - 197D
开场连wa三发A题,差点心态崩了,还好坚持打完了,一共A了三题 A题,判断能不能放第一个圆,能放的话,先手比赢 #include<map> #include<set> #inc ...
- STL标准容器特征
一. vector vector类是一种顺序容器,可以看作动态数组,容器中的元素存放在连续存储区域. vector容器自动分配.释放.扩展.收缩存储空间,不需要使用new或delete关键字. vec ...