一、先介绍一下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

最新文章

  1. nginx.conf中配置laravel框架站点
  2. JavaScript的理解记录(5)
  3. 「2014-3-11」HTTP 初步探究
  4. 省略号 对单行 多行的css
  5. iOS - Mac Apache WebDav 服务器配置
  6. 【转载】【Windows批处理IV】批量进行文件重命名
  7. 安装elasticsearch
  8. JavaScript设置cookie
  9. Mysql 数据库安装配置
  10. 3.RxJava详解
  11. 用spring-data-redis实现类似twitter的网站(转)
  12. 使用非 GUI 模式运行 JMeter 压力测试
  13. 脚本实现centos7修改二块网卡名称并配置ip信息
  14. 第一迭代目标——future weather
  15. Vue项目环境搭建(node+webpack)
  16. 安卓9.0系统机器(亲测有效)激活Xposed框架的步骤
  17. Quartz与Spring集成(二)
  18. HTTPS和SSL握手过程(转载)
  19. 位图法bitmap
  20. PAT A1098 Insertion or Heap Sort (25 分)——堆排序和插入排序,未完待续。。

热门文章

  1. Spring Boot 中使用jsp
  2. idea通过springboot初始化器新建项目
  3. Makefile文件应用——complicated项目
  4. HTML中a标签的锚点
  5. 通过wifi连接android设备的方法
  6. BZOJ4455/UOJ185 [Zjoi2016]小星星
  7. scala学习手记17 - 容器和类型推断
  8. C-RAN
  9. thinkphp &lt;eq&gt; &lt;if&gt;标签 condition中可以写PHP的判断逻辑
  10. LeetCode第[33]题(Java):Search in Rotated Sorted Array