Hibernate的缓存机制
2015-09-22 11:48
232 查看
Hibernate的缓存机制
缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的次数,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。
Hibernate在查询数据时,首先到缓存中去查找,如果找到就直接使用,找不到的时候就会从物理数据源中检索,所以,把频繁使用的数据加载到缓存区后,就可以大大减少应用程序对物理数据源的访问,使得程序的运行性能明显的提升.
Hibernate缓存分类:一级缓存、二级缓存和查询缓存;
一级缓存也叫session级缓存或事务级缓存,一级缓存的生命周期和Session的生命周期一致,也就是当
session关闭时缓存即被清除,一级缓存在Hibernate中是不可配置的,即不能被卸载。
二级缓存也称进程级缓存或SessionFactory级缓存,二级缓存可以被所有的session共享,二级缓存的生命周期和SessionFactory的生命周期一致。二级缓存在Hibernate中是可以配置的,可以通过class-cache配置类粒度级别的缓存(class-cache在class中数据发生任何变化的情况下自动更新),同时也可通过collection-cache配置集合粒度级别的缓存(collection-cache仅在
collection中增加了元素或者删除了元素的情况下才自动更新,也就是当collection中元素发生值的变化的情况下它是不会自动更新的)。
查询缓存,查询的结果集也可以被缓存。只有当经常使用同样的参数进行查询时,这才会有些用处。要使用查询缓存,首先你必须打开它:
hibernate.cache.use_query_cache true。该设置将会创建两个缓存区域 -
一个用于保存查询结果集(
另一个则用于保存最近查询的一系列表的时间戳(
请注意:在查询缓存中,它并不缓存结果集中所包含的实体的确切状态;它只缓存这些实体的标识符属性的值、以及各值类型的结果。
所以查询缓存通常会和二级缓存一起使用。绝大多数的查询并不能从查询缓存中受益,所以Hibernate默认是不进行查询缓存的。如若需要进行缓存,请调用
并将自己的结果集放到缓存中去。
查询缓存在Hibernate同样是可配置的,默认是关闭的,查询缓存的配置:
在hibernate.cfg.xml文件中启用查询缓存,如:
<property name="hibernate.cache.use_query_cache">true</property>
在程序中必须手动启用查询缓存,如:
query.setCacheable(true);
缓存自然会带来并发的访问问题,这个时候相应的就要根据应用来设置缓存所采用的事务隔离级别,和数据库的事务隔离级别概念基本一样,没什么多介绍的。
缓存的实现通过是通过key/value的Map方式来实现,在
Hibernate的一级、二级和查询缓存也同样如此,一级、二级缓存使用的key均为po的主键ID,value即为po实例对象,查询缓存使用的则为查询的条件、查询的参数、查询的页数,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认为该id对应的对象在数据库中一定存在。load方法在创建时首先会查询session,看看该id对应的对象是否存在,不存在则创建代理,实际用到该对象中的其他属性时才查询数据库,万一数据库中不存在该记录,才抛出异常。Load方法抛出异常是指在使用该对象的数据时,而不是在创建该对象的数据时。
一级缓存的管理:
evit(Object obj)
将指定的持久化对象从一级缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象.
clear()
将一级缓存中的所有持久化对象清除,释放其占用的内存资源
contains(Object obj)
判断指定的对象是否存在于一级缓存中.
flush()
刷新一级缓存区的内容,使之与数据库数据保持同步.
如何避免一次性大量实体数据入库导致内存溢出:先flush,然后clear
二级缓存的管理:
evict(Class arg0)
将指定类的所有持久化对象从二级缓存中清除,释放其占用的内存资源.
evict(Class arg0, Serializable arg1)
将某个类的指定ID的持久化对象从二级缓存中清除,释放对象所占用的资源.
evictCollection(String arg0)
将指定类的所有持久化对象的指定集合从二级缓存中清除,释放其占用的内存资源.
2、Session.get
在执行Session.get时,hibernate会确认一下该id对应的数据是否存在。get方法首先在session缓存中查询,没有的话然后在二级缓存中查询,最后查询数据库。
3、Query.list
在执行Query.list时,Hibernate的做法是首先检查是否配置了查询缓存,如配置了则从查询缓存中查找key为查询语句+查询参数+分页条件的值,如获取不到则从数据库中进行获取,从数据库获取到后Hibernate将会相应的填充一级、二级和查询缓存,如获取到的为直接的结果集,则直接返回,如获取到的为一堆id的值,则再根据id获取相应的值(Session.load),最后形成结果集返回,可以看到,在这样的情况下,list也是有可能造成N次的查询的。
查询缓存在数据发生任何变化的情况下都会被自动的清空。
4、Query.iterator
在执行Query.iterator时,和Query.list的不同的在于从数据库获取的处理上,Query.iterator向数据库发起的是
select id from这样的语句,也就是它是先获取符合查询条件的id,之后在进行iterator.next调用时才再次发起session.load的调用获取实际的数据。
可见,在拥有二级缓存并且查询参数多变的情况下,Query.iterator会比Query.list更为高效。
Hibernate的缓存机制
缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的次数,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。
Hibernate在查询数据时,首先到缓存中去查找,如果找到就直接使用,找不到的时候就会从物理数据源中检索,所以,把频繁使用的数据加载到缓存区后,就可以大大减少应用程序对物理数据源的访问,使得程序的运行性能明显的提升.
Hibernate缓存分类:一级缓存、二级缓存和查询缓存;
一级缓存也叫session级缓存或事务级缓存,一级缓存的生命周期和Session的生命周期一致,也就是当
session关闭时缓存即被清除,一级缓存在Hibernate中是不可配置的,即不能被卸载。
二级缓存也称进程级缓存或SessionFactory级缓存,二级缓存可以被所有的session共享,二级缓存的生命周期和SessionFactory的生命周期一致。二级缓存在Hibernate中是可以配置的,可以通过class-cache配置类粒度级别的缓存(class-cache在class中数据发生任何变化的情况下自动更新),同时也可通过collection-cache配置集合粒度级别的缓存(collection-cache仅在
collection中增加了元素或者删除了元素的情况下才自动更新,也就是当collection中元素发生值的变化的情况下它是不会自动更新的)。
查询缓存,查询的结果集也可以被缓存。只有当经常使用同样的参数进行查询时,这才会有些用处。要使用查询缓存,首先你必须打开它:
hibernate.cache.use_query_cache true。该设置将会创建两个缓存区域 -
一个用于保存查询结果集(
org.hibernate.cache.StandardQueryCache);
另一个则用于保存最近查询的一系列表的时间戳(
org.hibernate.cache.UpdateTimestampsCache)。
请注意:在查询缓存中,它并不缓存结果集中所包含的实体的确切状态;它只缓存这些实体的标识符属性的值、以及各值类型的结果。
所以查询缓存通常会和二级缓存一起使用。绝大多数的查询并不能从查询缓存中受益,所以Hibernate默认是不进行查询缓存的。如若需要进行缓存,请调用
Query.setCacheable(true)方法。这个调用会让查询在执行过程中时先从缓存中查找结果,
并将自己的结果集放到缓存中去。
查询缓存在Hibernate同样是可配置的,默认是关闭的,查询缓存的配置:
在hibernate.cfg.xml文件中启用查询缓存,如:
<property name="hibernate.cache.use_query_cache">true</property>
在程序中必须手动启用查询缓存,如:
query.setCacheable(true);
缓存自然会带来并发的访问问题,这个时候相应的就要根据应用来设置缓存所采用的事务隔离级别,和数据库的事务隔离级别概念基本一样,没什么多介绍的。
缓存的实现通过是通过key/value的Map方式来实现,在
Hibernate的一级、二级和查询缓存也同样如此,一级、二级缓存使用的key均为po的主键ID,value即为po实例对象,查询缓存使用的则为查询的条件、查询的参数、查询的页数,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认为该id对应的对象在数据库中一定存在。load方法在创建时首先会查询session,看看该id对应的对象是否存在,不存在则创建代理,实际用到该对象中的其他属性时才查询数据库,万一数据库中不存在该记录,才抛出异常。Load方法抛出异常是指在使用该对象的数据时,而不是在创建该对象的数据时。
一级缓存的管理:
evit(Object obj)
将指定的持久化对象从一级缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象.
clear()
将一级缓存中的所有持久化对象清除,释放其占用的内存资源
contains(Object obj)
判断指定的对象是否存在于一级缓存中.
flush()
刷新一级缓存区的内容,使之与数据库数据保持同步.
如何避免一次性大量实体数据入库导致内存溢出:先flush,然后clear
二级缓存的管理:
evict(Class arg0)
将指定类的所有持久化对象从二级缓存中清除,释放其占用的内存资源.
evict(Class arg0, Serializable arg1)
将某个类的指定ID的持久化对象从二级缓存中清除,释放对象所占用的资源.
evictCollection(String arg0)
将指定类的所有持久化对象的指定集合从二级缓存中清除,释放其占用的内存资源.
2、Session.get
在执行Session.get时,hibernate会确认一下该id对应的数据是否存在。get方法首先在session缓存中查询,没有的话然后在二级缓存中查询,最后查询数据库。
3、Query.list
在执行Query.list时,Hibernate的做法是首先检查是否配置了查询缓存,如配置了则从查询缓存中查找key为查询语句+查询参数+分页条件的值,如获取不到则从数据库中进行获取,从数据库获取到后Hibernate将会相应的填充一级、二级和查询缓存,如获取到的为直接的结果集,则直接返回,如获取到的为一堆id的值,则再根据id获取相应的值(Session.load),最后形成结果集返回,可以看到,在这样的情况下,list也是有可能造成N次的查询的。
查询缓存在数据发生任何变化的情况下都会被自动的清空。
4、Query.iterator
在执行Query.iterator时,和Query.list的不同的在于从数据库获取的处理上,Query.iterator向数据库发起的是
select id from这样的语句,也就是它是先获取符合查询条件的id,之后在进行iterator.next调用时才再次发起session.load的调用获取实际的数据。
可见,在拥有二级缓存并且查询参数多变的情况下,Query.iterator会比Query.list更为高效。
相关文章推荐
- 一份c/c++写日志到处都能用的代码
- 《Effective JavaScript》- 1.1 了解你使用的JavaScript版本
- SAX解析XML
- 【绝对干货来啦】巧用jax-rs之jersey实现不确定数量、多类型文件批量一次上传接口
- 检查iOS项目中是否使用了IDFA
- 一千行MySQL学习笔记(二)
- 未能加载文件或程序集“Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。
- 提交.a文件到svn
- J2ME编程中的几个重要概念介绍
- 刘强东内部分享:京东为什么能成功?因为做到了这一点
- View 随着手指的移动而放大和旋转
- dyld: Library not loaded: @rpath/QtWidgets.framework/Versions/5/QtWidgets
- 打印到类阵列的给定序列的所有排列的n皇后问题
- 2015 Objective-C 三大新特性
- 查阅参考资料的技巧
- C#/Net代码精简优化技巧(3)
- Spring MVC POST中文乱码解决方案
- Django搭建简单网页的学习笔记 之三(View)
- 【设计模式】——依赖倒转原则
- Android 搜索 把软键盘上的回车键改为搜索