【Hibernate 7】浅谈Hibernate的缓存机制
一、Hibernate缓存机制简介
对于Hibernate本身来说,它的缓存主要包括三部分:session缓存(一级缓存)、二级缓存、查询缓存。
1.1,session缓存
随着session的关闭而消失,load、iterator操作,会从一级缓存中查找数据,如果找不到,再到数据库里面查找。Query.list操作,如果没有配置查询缓存,将直接从数据库中获取数据。
特点:只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结束。事务范围的缓存使用内存作为存储介质,一级缓存属于事务范围。
1.2,二级缓存
hibernate并没有提供相应的二级缓存的组件,所以需要加入额外的二级缓存包,常用的二级缓存包是EHcache。这个我们在下载好的hibernate的lib下可以找到,然后将里面的几个jar包导入即可。
为什么要有二级缓存:
一级缓存是session级别,也就是事务级别的。当session关闭后,一级缓存就不存在了,当再次需要获取数据的时候,需要再次发送sql语句。为了解决session关闭,缓存失效的问题,我们配置二级缓存。
特点:
可以被应用范围内的所有事务共享访问,缓存的生命周期依赖于应用的生命周期,只有当应用结束时,缓存的生命周期才会结束。应用范围的缓存可以使用内存或硬盘作为存储介质,二级缓存属于应用范围。
1.3,查询缓存
所谓查询缓存,即让hibernate缓存list、iterator、createQuery等方法的查询结果集。如果没有打开查询缓存,hibernate将只缓存load方法获得的单个持久化对象。在打开了查询缓存之后,需要注意,调用query.list()操作之前,必须显式调用query.setCachable(true)来标识某个查询使用缓存。
二、实例分析二级缓存
2.1,配置二级缓存
首先,由于Hibernate的二级缓存是通过使用第三方包encache实现的,所以我们需要配置一个encache.xml的文件,来配置我们的缓存信息,并将这个文件放在项目根目录下
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><ehcache>
<!-- Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<!--指定二级缓存存放在磁盘上的位置-->
<diskStore path="user.dir"/>
<!--我们可以给每个实体类指定一个对应的缓存,如果没有匹配到该类,则使用这个默认的缓存配置-->
<defaultCache
maxElementsInMemory="10000" //在内存中存放的最大对象数
eternal="false" //是否永久保存缓存,设置成false
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true" //如果对象数量超过内存中最大的数,是否将其保存到磁盘中,设置成true
/>
<!--
1、timeToLiveSeconds的定义是:以创建时间为基准开始计算的超时时长;
2、timeToIdleSeconds的定义是:在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长;
3、如果仅设置了timeToLiveSeconds,则该对象的超时时间=创建时间+timeToLiveSeconds,假设为A;
4、如果没设置timeToLiveSeconds,则该对象的超时时间=max(创建时间,最近访问时间)+timeToIdleSeconds,假设为B;
5、如果两者都设置了,则取出A、B最少的值,即min(A,B),表示只要有一个超时成立即算超时。
-->
<!--可以给每个实体类指定一个配置文件,通过name属性指定,要使用类的全名-->
<cache name="com.angel.hibernate.Student"
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="10000"
timeToLiveSeconds="10000"
overflowToDisk="true"
/>
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
</ehcache></span></span>
其次,配置Hibernate.cfg.xml文件,启用二级缓存
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"></pre><pre name="code" class="html"> <!-- 配置缓存提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!--Hibernate4以上的提供商配置
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
-->
<!-- 启用二级缓存,这也是它的默认配置 -->
<property name="hibernate.cache.use_second_level_cache">true</property> <!-- 二级缓存配置文件的位置 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property> <!-- 指定Student使用二级缓存 -->
<class-cache class="com.angel.hibernate.Student" usage="read-only"/></span></span>
2.2,配置实体映射文件的缓存
<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.Student" table="t_student">
<!-- 二级缓存一般设置为只读的 -->
<cache usage="read-only"/>
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="classes" column="classesid"/>
</class>
</hibernate-mapping></span></span>
2.3,实例测试二级缓存
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">/**
* 开启二级缓存
*
* 在两个session中发load查询
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
} try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1); //不会发出查询语句,因为配置二级缓存,session可以共享二级缓存中的数据
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}</span></span>
三、实例分析查询缓存
首先,Hibernate.cfg.xml配置
<span style="font-family:KaiTi_GB2312;font-size:18px;"><!-- 启用查询缓存,默认是false是不起用的 -->
<property name="hibernate.cache.use_query_cache">true</property></span>
其次,在应用缓存是还需要开启查询缓存
<span style="font-family:KaiTi_GB2312;font-size:18px;">List names = session.createQuery("select s.name from Student s").setCacheable(true).list();</span>
注意:
1,查询缓存,和session的生命周期没有联系,它同样属于应用程序级别的缓存
2,使用query.iterate()查询普通的属性,将不会启动查询缓存,查询缓存只对query.list()起作用
3,如果关闭二级缓存,只启用查询缓存,那么查询缓存会缓存实体对象的id,当第二次执行query.list的时候,将缓存中的id取出,分别到一级和二级缓存中查询相对应的实体,如果存在,则直接使用对象,否则发出查询的sql语句。而如果我们关闭二级缓存,那么查询时将不能再缓存中找到实体对象,则会发出N条查询子句,将再次引起N+1问题,所以在应用查询缓存的时候,一定要开启二级缓存。
四、总结
以上就是Hibernate中关于缓存机制的总结,但在实际应用中,我们仍然需要对缓存进行管理,比如:
一级缓存的管理:
1,evit(Object obj) 将指定的持久化对象从一级缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象
2,clear() 将一级缓存中的所有持久化对象清除,释放其占用的内存资源
3,contains(Object obj) 判断指定的对象是否存在于一级缓存中
4,flush() 刷新一级缓存区的内容,使之与数据库数据保持同步
二级缓存的管理:
1,evict(Class arg0, Serializable arg1) 将某个类的指定ID的持久化对象从二级缓存中清除,释放对象所占用的资源
2,evict(Class arg0) 将指定类的所有持久化对象从二级缓存中清除,释放其占用的内存资源
3,evictCollection(String arg0) 将指定类的所有持久化对象的指定集合从二级缓存中清除,释放其占用的内存资源
【Hibernate 7】浅谈Hibernate的缓存机制的更多相关文章
- 浅谈:Redis持久化机制(一)RDB篇
浅谈:Redis持久化机制(一)RDB篇 众所周知,redis是一款性能极高,基于内存的键值对NoSql数据库,官方显示,它的读效率可达到11万次每秒,写效率能达到8万次每秒,因为它基于内存以及存 ...
- 浅谈:Redis持久化机制(二)AOF篇
浅谈:Redis持久化机制(二)AOF篇 上一篇我们提及到了redis的默认持久化方式RDB,是一种通过存储快照数据方式持久化的机制,它在宕机后会丢失掉最后一次更新RDB文件后的数据,这也是由于它 ...
- 浅谈mysql innodb缓存策略
浅谈mysql innodb缓存策略: The InnoDB Buffer Pool Innodb 持有一个存储区域叫做buffer pool是为了在内存中缓存数据和索引,知道innodb buffe ...
- 浅谈Java的反射机制和作用
浅谈Java的反射机制和作用 作者:Java大师 欢迎转载,转载请注明出处 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象 ...
- 从一次异常中浅谈Hibernate的flush机制
摘自http://www.niwozhi.net/demo_c70_i1482.html http://blog.itpub.net/1586/viewspace-829613/ 这是在一次事务提交时 ...
- Hibernate中的HQL查询与缓存机制
HQL:完全面向对象查询 SQL的执行顺序: 1.From 2.Where 过滤基础数据 where与having的区别:1.顺序不同 2.where过滤基础数据 3. 过滤聚合函数 3.Group ...
- 浅谈hibernate的sessionFactory和session
一.hibernate是什么? Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hiber ...
- Hibernate第二天——实体类 与缓存机制
第二天,我们先来了解一下框架里的一个重要概念:实体类 实体类:把数据表或其它持久化数据的格式映射成的类,就是实体类. 实体类的编写规则:由于对应的是javabean,因而也遵循javabean的一些规 ...
- 浅谈Hibernate入门
前言 最近打算做一个自己的个人网站,经过仔细思考,打算使用hibernate作为开发的ORM框架,因此各种找资料,由于本人是刚刚接触这技术的,所以就找了比较基础的知识来分享下 基本概述 Hiberna ...
随机推荐
- MappedByteBuffer读写文件
一. MappedByteBuffer java把文件映射到内存中,避免堆内存产生大对象引起full gc.mappedByteBuffer的读写速度都要超过堆内读写文件的速度 public clas ...
- java面试常考题
基础知识: 1.C++或Java中的异常处理机制的简单原理和应用. 当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常.违反语义规则包括2种情况.一种是JAVA类库 ...
- 值得推荐的C/C++框架和库 (真的很强大)
值得学习的C语言开源项目 - 1. Webbench Webbench是一个在Linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的 ...
- Oracle数据库 External component has thrown an exception
出现这种错误一般是在SQL语句执行前就报出的错误.这样的错误一般需要仔细检查SQL语句,以及参数的数据类型. 而在cmd.ExecuteNonQuery()中出现的错误,则很可能就排除了语法类的错误. ...
- Java多线程之简单的线程同步实例
数据类: package Thread.MyCommon; public class Data { public int num = 0; public synchronized int getEve ...
- 拥抱高效、拥抱 Bugtags 之来自用户的声音
小编按:这是一篇 Bugtags 用户来稿,主要是介绍了 Bugtags 使用的方法及其带来的效率的提升,谢谢介博同学对 Bugtags 的信赖和支持.小编在这里诚邀各位热心用户向我们投稿,说出你使用 ...
- Thinkpad X240在Centos 7下使用ID 138a:0017或者vfs5011指纹识别
我的笔记本是ThinknPad X240,自带的指纹识别器,通过命令lsusb可以查看: [zz@zz ~]$ lsusb Bus 001 Device 002: ID 24ae:2003 Bus 0 ...
- expdp impdp终极教学
源地址:http://blog.csdn.net/giianhui/article/details/7788550
- C++学习5
类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量:创建对象的过程也叫类的实例化.每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数. 与结构体一样,类 ...
- Servlet中读取参数的几种方式
为每一Servlet设置初始化参数 可以为每一个Servlet在对应的web.xml中的Servlet节点下编写初始化参数,格式如下: <init-param> <param-nam ...