- 浏览: 176565 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
dupeng41255:
问一下,。com的接口 是不是需要注册啊?我调用的时候返回说需 ...
java实现whois域名查询 -
feiyu86:
比喻的非常贴切。。
synchronized方法和代码块的使用 -
罡风笑:
贴结果:CBH 蜀汉 绝顶 刀客
开心一下 你古代的身份。超级好玩~
Hibernate获取数据的方式有不同的几种,其与缓存结合使用的效果也不尽相同,而Hibernate中具体怎么使用缓存其实是我们很关心的一个问题,直接涉及到性能方面。
缓存在Hibernate中主要有三个方面:一级缓存、二级缓存和查询缓存
①一级缓存在Hibernate中对应的为session范围的缓存,也就是当session关闭时缓存即被清除,一级缓存在Hibernate中是不可配置的
②二级缓存在Hibernate中对应的为SessionFactory范围的缓存,通常来讲SessionFactory的生命周期和应用的生命周期相同,所以可以看成是进程缓存或集群缓存,二级缓存在Hibernate中是可以配置的,可以通过class-cache配置类粒度级别的缓存(class-cache在class中数据发生任何变化的情况下自动更新),同时也可通过collection-cache配置集合粒度级别的缓存(collection-cache仅在collection中增加了元素或者删除了元素的情况下才自动更新,也就是当collection中元素发生值的变化的情况下它是不会自动更新的),跨session的缓存自然会带来并发的访问题,这个时候相应的就要根据应用来设置缓存所采用的事务隔离级别,和数据库的事务隔离级别概念基本一样,没什么多介绍的
③查询缓存在Hibernate同样是可配置的,默认是关闭的,可以通过设置cache.use_ query_cache为true来打开查询缓存。
根据缓存的通常实现策略,我们可以来理解Hibernate的这三种缓存,缓存的实现通过是通过key/value的Map方式来实现,在Hibernate的一级、二级和查询缓存也同样如此。一级、二级缓存使用的key均为po的主键ID,value即为po实例对象,查询缓存使用的则为查询的条件(hql转化而成的sql语句)、查询的参数、查询的页数,value有两种情况,如果采用的是select po.property这样的方式那么value为整个结果集,如采用的是from这样的方式那么value为获取的结果集中各po对象的主键ID,这样的作用很明显,节省内存。
简单介绍完Hibernate的缓存后,再结合Hibernate的获取数据方式来说明缓存的具体使用方式,在Hibernate中获取数据常用的方式主要有四种:Session.load、Session.get、Query.list、Query.iterator。
1、Session.load
在执行session.load时,Hibernate首先从当前session的一级缓存中获取id对应的值,在获取不到的情况下,将根据该对象是否配置了二级缓存来做相应的处理,如配置了二级缓存,则从二级缓存中获取id对应的值,如仍然获取不到则还需要根据是否配置了延迟加载来决定如何执行,如未配置延迟加载则从数据库中直接获取,在从数据库获取到数据的情况下,Hibernate会相应的填充一级缓存和二级缓存,如配置了延迟加载则直接返回一个代理类,只有在触发代理类的调用时才进行数据库查询的操作。
备注 load方法过程:一级缓存 ---> 二级缓存 ----> DB访问 ---> 填充一级缓存[、二级缓存] / 返回一个代理类
在这样的情况下我们就可以看到,在session一直打开的情况下,要注意在适当的时候对一级缓存进行刷新操作,通常是在该对象具有单向关联维护的时候,在Hibernate中可以使用象session.clear、session.evict的方式来强制刷新一级缓存。 二级缓存则在数据发生任何变化(新增、更新、删除)的情况下都会自动的被更新。
备注:由于一级缓存是位于物理内存空间的,毕竟大小有限。过多的对象缓存在这里会造成较大的压力。适当的时候刷新缓存除了可以保证数据库和内存的状态同步外,还可以移除不再用的对象,腾出空间来给后面的对象缓存使用。
2、Session.get
在执行Session.get时,和Session.load不同的就是在当从缓存中获取不到时,直接从数据库中获取id对应的值。
备注:load和get方法的另外一个区别就是:当对象在DB中找不到时,load会抛出异常,而get仅仅返回null
3、Query.list
在执行Query.list时,Hibernate的做法是首先检查是否配置了查询缓存,如配置了则从查询缓存中查找key为查询语句+查询参数+分页条件的值,如获取不到则从数据库中进行获取,从数据库获取到后Hibernate将会相应的填充一级、二级和查询缓存,如获取到的为直接的结果集,则直接返回,如获取到的为一堆id的值,则再根据id获取相应的值(Session.load),最后形成结果集返回,可以看到,在这样的情况下,list也是有可能造成N次的查询的。
查询缓存在数据发生任何变化的情况下都会被自动的清空。
备注:list()方法的SQL成本
①没有配置查询缓存或者缓存匹配不到时,发出一次SQL查询
②缓存的值为一组对象ID,则每个ID执行一次Session.load操作。视乎缓存对象是否还在会再发出0~N次SQL查询
③缓存的值为一组集合对象,则直接返回。此时不需要发出SQL查询
由此可见list()方法的SQL成本从0~N次不等,具体的次数和一、二级缓存的对象生命周期时间设置、SQL语句写法有关。如果采用select po.value写法,那么SQL成本最低(0),如果采用from po写法,那么SQL成本从0~N不等。
虽然表明看采用select po.value的写法好像会更加高效,但是考虑到对象的大小,但一次性读入时会造成大量的内存空间浪费。但是缓存ID又可能带来N次额外的查询消耗,应该怎么办呢?最好的方法就是设置一、二级缓存的对象生命周期时间比查询缓存的生命周期长,这样不至于在Hibernate对每个ID执行Session.load方法时实体缓存都过期而被清空了。
另外一个要注意的是:如果查询缓存引用的表在查询后被修改了,那么不管缓存的数据是否有变,该查询都会被清空而重新获取。因为Hibernate是靠比较每个表的修改时间和查询缓存的填入时间来判断表是否被修改了,它不会去判断具体的内容
4、Query.iterator
在执行Query.iterator时,和Query.list的不同的在于从数据库获取的处理上,Query.iterator向数据库发起的是select id from这样的语句,也就是它是先获取符合查询条件的id,之后在进行iterator.next调用时才再次发起session.load的调用获取实际的数据。
可见,在拥有二级缓存并且查询参数多变的情况下,Query.iterator会比Query.list更为高效。
备注:iterator的SQL成本
①最佳情况下,只有一次SQL查询(ID查询),其它的通过一、二级缓存可以得到
②最坏情况下,变成1+N次查询(ID查询 + 实体查询)
这四种获取数据的方式都各有适用的场合,要根据实际情况做相应的决定,最好的方式无疑就是打开show_sql选项看看执行的情况来做分析,系统结构上只用保证这种调整是容易实现的就好了,在cache这个方面的调整自然是非常的容易,只需要调整配置文件里的设置,而查询的方式则可对外部进行屏蔽,这样要根据实际情况调整也非常容易。
备注:关于list()和iterator()的查询成本比较
※没有配置查询缓存,或者缓存中没有对应的key :
list():执行一次SQL查询全部取出
iterator():执行一次SQL语句先取出符合条件的所有对象ID,在迭代期间通过Session.load方法查询(额外的0~N次查询)
※缓存值是一组对象ID:
list():执行Session.load方法查询(额外的0~N次查询)
iterator():执行Session.load方法查询(额外的0~N次查询)
※缓存值是一组集合:
list():直接返回,没有SQL查询
iterator():直接返回,没有SQL查询
可见最大的区别在于从数据库读取数据的地方,list虽然只有1次SQL查询,但它是直接从物理数据文件中读取。而iterator虽然是1+N次查询,但后面的N次可能是从缓存中拿数据,所以SQL语句次数相同,兼之iterator只取id,在缓存配置得当的情况下,iterator确实高效。但是如果缓存配置不当,那么iterator的后续next操作将不得不发出一次又一次的SQL查询,反而大大比不上list。
从分页查询的情况来看,用iterator()的效率反而不及list():因为每页的对象的id都是不同的。iterator()使用Session.load时总是读取不到实体缓存(一级、二级缓存)的值,只能再发出一次SQL查询。
发表评论
-
Eclipse 中Hibernate tools 的安装和使用
2014-09-23 20:21 741eclipse 远程安装hibernate插件 自动生成mo ... -
Java关键字final、static使用总结
2011-05-24 12:31 966一、final 根据程序上下文环境,Java关键字final ... -
Ubuntu下jdk的几种不用的环境变量配置
2011-04-08 16:30 21081.安装ubuntu下的jdk 到s ... -
快速递归排序及2分查找
2011-04-06 13:55 1252import java.util.Arrays; pub ... -
Java synchronized用法搜集
2010-08-21 11:13 21851、synchronized关键字的作用域有二种: 1 ... -
生产者与消费者例子(多线程wait()与notifyAll应用)
2010-05-25 16:42 1028package test; import java.ut ... -
synchronized块及方法应用
2010-05-24 16:02 874package test; class Obj impl ... -
run()外部捕获run()内未捕获的异常
2010-05-24 11:25 930package test; import java.ut ... -
java注解简单应用
2010-05-21 13:38 1662package test; import java.la ... -
enum版本石头剪刀布
2010-05-20 15:24 1128package test; public enum Ou ... -
PowerDesigner建模资料
2010-04-22 01:02 988PowerDesigner建模资料 -
jquery帮助文档
2010-04-21 23:49 1054很有用的帮助文档,见附件 -
URLConnection的连接、超时、关闭用法总结
2010-04-07 20:54 4854Java中可以使用HttpURLConne ... -
螺旋矩阵(顺时针内转)
2010-03-11 15:47 1476import java.util.Arrays; pub ... -
java面试题库
2010-03-08 00:23 774java的一些常见的题集,学习和面试好帮手 -
Apache tomcat集群总结
2010-03-06 03:33 11241.去掉apache中httpd.conf目录中以下几行的注释 ... -
Apache负载均衡设置方法: mod_proxy
2010-03-06 03:28 1112WebjxCom提示:一般来说 ... -
apache中文文档
2010-03-06 01:40 949apache环境配置中的必要手册 -
kxml源码
2010-03-02 23:17 998非常有用的XML解析器,小巧玲珑 -
FckEditor(java版)配置方法
2009-12-09 13:51 1092一,下载fckeditor包 fckeditor-java- ...
相关推荐
本篇将详细探讨如何使用Hibernate ORM框架结合EhCache实现数据缓存的处理,从而提高系统的响应速度。 Hibernate是一个流行的Java持久化框架,它提供了一种便捷的方式来映射对象关系模型(ORM)到关系数据库。然而,...
### Hibernate使用缓存时的数据同步问题详解 #### 引言 在现代软件开发中,ORM框架如Hibernate被广泛应用于数据库操作,以简化Java应用程序与数据库之间的交互。然而,使用Hibernate时,缓存机制的合理配置对于...
缓存的配置与使用 在实际项目中,合理配置和使用缓存可以极大地提升应用性能。这包括选择合适的缓存提供商、设置缓存策略、决定哪些实体或查询结果应放入缓存等。开发者需要根据业务需求和系统负载进行权衡,以...
2. **配置实体缓存策略**:针对每个需要缓存的实体,我们需要在对应的映射文件(.hbm.xml)或者使用注解方式声明缓存策略。例如,我们可以使用`@Cacheable`和`@Cache`注解: ```java @Entity @Table(name = "USER...
- **数据更新**:对于频繁更新的数据,使用二级缓存的意义不大,因为需要频繁同步缓存与数据库,反而可能导致数据不一致。 - **范围分类**:二级缓存分为事务范围、进程范围和集群范围: - **事务范围**:只对当前...
一级缓存与二级缓存 #### 1.1 一级缓存 一级缓存是 Hibernate 内置的 Session 缓存,它是每个 Hibernate Session 的私有缓存。当对象被加载到 Session 中时,它们会被自动缓存。在同一个 Session 内部,对相同...
创建一个简单的服务,查询并查看是否从缓存中获取数据,例如: ```java @RestController public class MyController { @Autowired private MyEntityRepository repository; @GetMapping("/test") public ...
这与一级缓存(Session级别)不同,一级缓存仅存在于单个Session生命周期内,当Session关闭时,一级缓存中的数据会丢失。二级缓存的存在减少了对数据库的直接访问,从而提高了数据读取速度。 为了启用Hibernate的二...
### Hibernate的映射、三态、脏数据、Session缓存详解 #### 一、Hibernate映射 **Hibernate映射**是Hibernate框架的核心功能之一,它实现了Java对象与数据库表之间的映射关系。通过这种方式,开发人员可以使用面向...
Hibernate 二级缓存是针对SessionFactory级别的全局缓存,与一级缓存(Session级别)不同,一级缓存只在单个Session生命周期内有效。二级缓存则允许不同Session之间共享数据,提高了数据访问效率,减少了对数据库的...
本篇将深入探讨Hibernate的一级缓存和二级缓存,以及查询缓存的配置和使用。 ### 一级缓存 一级缓存是Hibernate默认提供的缓存,它是Session级别的,每个Hibernate Session都有一个私有的、本地的一级缓存。当我们...
这里它被用作Hibernate二级缓存的实现方式,这意味着当数据首次从数据库中读取后,会被存储在memcached中,后续请求可以直接从缓存中获取,避免了频繁的数据库交互,从而提高了系统的响应速度。 **知识点详解:** ...
Hibernate的一级缓存和二级缓存是提高数据访问效率的重要手段,它们各自承担着不同的角色,合理使用可以显著提升应用性能。然而,缓存的使用也需要谨慎,需要根据具体业务场景选择合适的缓存策略,并关注可能带来的...
在Java的持久化框架Hibernate中,二级缓存是提高数据访问效率的重要机制。它是一种全局共享的、跨会话的数据存储区域,旨在减少对数据库的直接访问,从而降低系统负载,提升性能。在这个"hibernate二级缓存实例"中,...
5. **缓存同步**:为了确保数据一致性,Hibernate提供了一些机制来同步缓存与数据库,如使用版本号或时间戳进行脏检查。 6. **缓存优化**:正确配置缓存的大小、过期策略和缓存级别对于性能提升至关重要。过度缓存...
然而,由于对象模型和关系型数据库模型之间的映射会产生一定的性能开销,Hibernate引入了一套缓存机制来提高数据访问的效率。 #### 二、Hibernate的缓存结构 Hibernate的缓存机制分为两层:第一级缓存(Session...
当数据从数据库中加载时,Hibernate会尝试将这些对象放入二级缓存,后续的相同查询就可以直接从缓存中获取结果,避免了额外的数据库查询。这有助于提高性能,尤其是在处理重复查询时。 配置和选择二级缓存实现是...
《深入理解Hibernate的一级缓存与二级缓存》 Hibernate作为一款强大的ORM框架,其缓存机制是优化数据库操作性能的关键之一。缓存主要分为一级缓存和二级缓存,它们各自承担着不同的职责,共同提升了数据访问的效率...
缓存中存储的是数据库数据的副本,当需要查询数据时,Hibernate会首先在缓存中查找,如果找到,就直接返回,避免了数据库查询的开销。 **1. Hibernate缓存概述** Hibernate提供了两级缓存:一级缓存和二级缓存。一...