Hibernate缓存分类:

一、Session缓存(又称作事务缓存):Hibernate内置的,不能卸除。

缓存范围:缓存只能被当前Session对象访问。缓存的生命周期依赖于Session的生命周期,当Session被关闭后,缓存也就结束生命周期。

二、SessionFactory缓存(又称作应用缓存):使用第三方插件,可插拔。

缓存范围:缓存被应用范围内的所有session共享,不同的Session可以共享。这些session有可能是并发访问缓存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用程序范围。

缓存:但是一般人的理解在内存中的一块空间,可以将二级缓存配置到硬盘。用白话来说,就是一个存储数据的容器。我们关注的是,哪些数据需要被放入二级缓存。

缓存:是计算机领域的概念,它介于应用程序和永久性数据存储源之间。

作用:降低应用程序直接读写数据库的频率,从而提高程序的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存。

Hibernate的缓存一般分为3类:

一级缓存

二级缓存

查询缓存

如果希望一个Java对象一直处于声明周期中,就必须保证至少有一个变量引用它,或者在一个Java集合中存放了这个对象的引用。在Session接口的实现咧SessionImpl中定义了一系列的Java集合,这些Java集合构成了Session的缓存。

以下方法支持一级缓存:金牌结论

* get() 
    * load() 
    * iterate(查询实体对象) 
其中 Query 和Criteria的list() 只会缓存,但不会使用缓存(除非结合查询缓存)。

一级缓存

01.Session内的缓存即一级缓存,内置且不能被卸载,一个事务内有效。

02.Session为应用程序提供了管理缓存的方法:

evict(Object o)

clear()

03.金牌讲解一级缓存

一级缓存的生命周期和session的生命周期一致,当前session一旦关闭,一级缓存就消失了,因此一级缓存也叫session级的缓存或事务级缓存,一级缓存只存实体对象,它不会缓存一般的对象属性(查询缓存可以),即当获得对象后,就将该对象缓存起来,如果在同一session中再去获取这个对象时,它会先判断在缓存中有没有该对象的id,如果有则直接从缓存中获取此对象,反之才去数据库中取,取的同时再将此对象作为一级缓存处理。

二级缓存

开发中的用于没有面试带来作用大。

二级缓存是进程或集群范围内的缓存,可以被所有的Session共享

二级缓存是可配置的插件

二级缓存的配置使用(ehcache缓存)

*.引入如下jar包。
ehcache-1.2..jar 核心库
backport-util-concurrent.jar
commons-logging.jar
*.配置Hibernate.cfg.xml开启二级缓存
<property name="hibernate.cache.use_second_level_cache">true</property>
*.配置二级缓存的供应商
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
*.指定使用二级缓存的类
方案一:在*.hbm.xml中配置
在<class元素的子元素下添加chche子节点,但该配置仅会缓存对象的简单属性,若希望缓存集合属性中的元素,必须在set元素中添加<cache>子元素
<class name="Student" table="STUDENT">
<cache usage="read-write"/>

在大配置文件(hibernate.cfg.xml)中配置

<class-cache usage="read-write" class="cn.happy.entity.Student"/>


<collection-cache usage="read-write" collection=""/>


*5.在src下添加ehcache.xml文件,从etc获取文件即可。

测试: 二级缓存  数据散装  的特点

 Session session = HibernateUtil.getSession();
Transaction tx=session.beginTransaction();
Dept dept = (Dept)session.get(Dept.class,);
System.out.println(dept); Dept dept2 = (Dept)session.get(Dept.class,);
System.out.println(dept2);
tx.commit(); Session session2 = HibernateUtil.getSession();
Transaction tx2=session2.beginTransaction();
Dept dept3 = (Dept)session2.get(Dept.class,);
System.out.println(dept3);
tx2.commit();

解析:每次从二级缓存中取出的对象,都是一个新的对象。、

测试:  使用list 将数据存储到二级缓存中(只能往二级缓存中存数据 不能取出数据)  在从二级缓存中取出数据时 会重新从数据库取数据(重新生成sql)

List<Carport> list = session.createQuery("from Carport").list();
System.out.println(list.get().getLocation()); HibernateUtil.closeSession();
System.out.println("=========="); Session session2 = (Session) HibernateUtil.getSession();
List<Carport> list2 = session2.createQuery("from Carport").list();
System.out.println(list.get().getLocation());

解析: 可以看到   我们上面的list()操作仅仅是将数据存储到了缓存中    却不能从内存中取出数据(生成了第二道sql查询语句)。

测试:iterator()方法可以读取二级缓存中的数据

首先说明:

iterator()会先到数据库中把id都取出来,然后真正要遍历某个对象的时候先到缓存中找,如果找不到,以id为条件再发一条sql到数据库,

这样如果缓存中没有数据,则查询数据库的次数为n+1。    iterate中返回的对象是代理对象

 Query query = session.createQuery("from Carport");
Iterator iterate = query.iterate();
while (iterate.hasNext()) {
System.out.println(((Carport)iterate.next()).getLocation());
} HibernateUtil.closeSession();
System.out.println("=========="); Session session2 = (Session) HibernateUtil.getSession();
Query query2 = session2.createQuery("from Carport");
Iterator iterate2 = query2.iterate();
while (iterate2.hasNext()) {
System.out.println(((Carport)iterate2.next()).getLocation());
}

解析:要遍历某个对象的时候先到缓存中找,如果找不到,以id为条件再发一条sql到数据库。(iterator()可以从缓存中取出数据来)

测试: 集合级别缓冲区

二级缓存的策略

当多个并发的事务同时访问持久化层的缓存中的相同数据时,会引起并发问题,必须采用必要的事务隔离措施。

在进程范围或集群范围的缓存,即第二级缓存,会出现并发问题。因此可以设定以下4种类型的并发访问策略,每一种策略对应一种事务隔离级别。

●   只读缓存(read-only)

如果应用程序需要读取一个持久化类的实例,但是并不打算修改它们,可以使用read-only缓存。这是最简单,也是实用性最好的策略。

对于从来不会修改的数据,如参考数据,可以使用这种并发访问策略。

●   读/写缓存(read-write)

如果应用程序需要更新数据,可能read-write缓存比较合适。如果需要序列化事务隔离级别,那么就不能使用这种缓存策略。

对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题。

●   不严格的读/写缓存(nonstrict-read-write)

如果程序偶尔需要更新数据(也就是说,出现两个事务同时更新同一个条目的现象很不常见),也不需要十分严格的事务隔离,可能适用nonstrict-read-write缓存。

对于极少被修改,并且允许偶尔脏读的数据,可以采用这种并发访问策略。

●   事务缓存(transactional)

transactional缓存策略提供了对全事务的缓存,仅仅在受管理环境中使用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。

在上面所介绍的隔离级别中,事务型并发访问策略的隔离级别最高,然后依次是读/写型和不严格读写型,只读型的隔离级别最低。事务的隔离级别越高,并发性能就越低。

查询缓存

1,查询是数据库技术中最常用的操作,Hibernate为查询提供了缓存,用来提高查询速度,优化查询性能

相同HQL语句检索结果的缓存!

2,查询缓存依赖于二级缓存

查询缓存是针对普通属性结果集的缓存,对实体对象的结果集只缓存id(其id不是对象的真正id,可以看成是HQL或者SQL语句,它与查询的条件相关即where后的条件相关,不同的查询条件,其缓存的id也不一样)。查询缓存的生命周期,当前关联的表发生修改或是查询条件改变时,那么查询缓存生命周期结束,它不受一级缓存和二级缓存生命周期的影响,要想使用查询缓存需要手动配置如下:

 * 在hibernate.cfg.xml文件中启用查询缓存,如: 
    <property name="hibernate.cache.use_query_cache">true</property>
    * 在程序中必须手动启用查询缓存,如: 
    query.setCacheable(true); 
其中 Query 和Criteria的list() 就可利用到查询缓存了。

注意:

不要想当然的以为缓存可以提高性能,仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的。在不了解原理的情况下乱用,可能会有1+N的问题。不当的使用还可能导致读出脏数据。 如果受不了hibernate的诸多限制,那么还是自己在应用程序的层面上做缓存吧。

在越高的层面上做缓存,效果就会越好。就好像尽管磁盘有缓存,数据库还是要实现自己的缓存,尽管数据库有缓存,咱们的应用程序还是要做缓存。因为底层的缓存它并不知道高层要用这些数据干什么,只能做的比较通用,而高层可以有针对性的实现缓存,所以在更高的级别上做缓存,效果也要好些吧。

缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为了减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能. 
    Hibernate在查询数据时,首先到缓存中去查找,如果找到就直接使用,找不到的时候就会从物理数据源中检索,所以,把频繁使用的数据加载到缓存区后,就可以大大减少应用程序对物理数据源的访问,使得程序的运行性能明显的提升.

 

后续更新。。。

 

话说:Hibernate二级缓存的更多相关文章

  1. Hibernate ——二级缓存

    一.Hibernate 二级缓存 1.Hibernate 二级缓存是 SessionFactory 级别的缓存. 2.二级缓存分为两类: (1)Hibernate内置二级缓存 (2)外置缓存,可配置的 ...

  2. 配置Hibernate二级缓存时,不能初始化RegionFactory的解决办法

    配置Hibernate 二级缓存时,出现以下bug提示: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder&quo ...

  3. 配置Hibernate二级缓存步骤

    配置Hibernate二级缓存步骤: 加入二级缓存的jar包及配置文件 jar包位置:hibernate-release-4.1.8.Final\lib\optional\ehcache下所有jar包 ...

  4. Hibernate 二级缓存 总结整理(转)

    和<Hibernate 关系映射 收集.总结整理> 一样,本篇文章也是我很早之前收集.总结整理的,在此也发上来 希望对大家有用.因为是很早之前写的,不当之处请指正. 1.缓存:缓存是什么, ...

  5. Hibernate(十六):Hibernate二级缓存

    Hibernate缓存 缓存(Cache):计算机领域非常通用的概念.它介于应用程序和永久性数据存储源(如磁盘上的文件或者数据库)之间,起作用是降低应用程序直接读取永久性数据存储源的频率,从而提高应用 ...

  6. hibernate二级缓存demo2

    @Test public void hello3(){ Session session=sessionFactory.openSession(); List list = session.create ...

  7. hibernate二级缓存整合

    <?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http:// ...

  8. ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存

    ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存 hibernate  : Hibernate是一个持久层框架,经常访问物理数据库 ...

  9. spring boot集成ehcache 2.x 用于hibernate二级缓存

    https://www.jianshu.com/p/87b2c309b776 本文将介绍如何在spring boot中集成ehcache作为hibernate的二级缓存.各个框架版本如下 spring ...

  10. js相关(easyUI),触发器,ant,jbpm,hibernate二级缓存ehcache,Javamail,Lucene,jqplot,WebService,regex,struts2,oracle表空间

    *********************************************js相关********************************************* // 在指 ...

随机推荐

  1. 《Spring Boot 那些事》

    <Spring Boot 那些事>----https://www.bysocket.com/?p=1124

  2. HBase shell的常用命令(CRUD)

    @来源是传智播客hadoop的视频教程,觉得入门不错,就copy过来了 一.启动HBase: sudo -i  cd /home/cx/itcast/hbase-1.2.6/bin  ./start- ...

  3. Oracle 11.2.0.4.0安装

    http://opensgalaxy.com/2015/08/25/oracle11-2-0-4-0%E5%AE%89%E8%A3%85%E5%8F%8A%E8%A1%A5%E4%B8%81%E8%8 ...

  4. Spring实现封装自定义注解@Trimmed清除字符串前后的空格

    在Spring中实现字符串清除的方法有很多,原生方法String自带trim()方法,或者使用StringUtils提供的trim...方法. 通常可以将上面的方式封装成自定义注解的形式去实现来节省更 ...

  5. CentOS 7: 设置时区和时间

    查看当前时区和时间 $ date $ ls -l /etc/localtime 查看所有可用时区 $ timedatectl list-timezones | grep Asia 设置时区 $ tim ...

  6. JNI/NDK开发指南(三)——JNI数据类型及与Java数据类型的映射关系

    转载请注明出处:http://blog.csdn.net/xyang81/article/details/42047899 当我们在调用一个Java native方法的时候.方法中的參数是怎样传递给C ...

  7. golang中select case 的用途到底是啥

    https://nanxiao.gitbooks.io/golang-101-hacks/content/posts/select-operation.html ------------------- ...

  8. Java深入浅出系列(四)——深入剖析动态代理--从静态代理到动态代理的演化

    静态代理 如上图,在程序执行之前.程序猿就要编写Proxy.然后进行编译,即在程序执行之前,代理类的字节码文件就已经生成了(Proxy类的class文件已经存在了). 静态代理尽管在增强现有的接口业务 ...

  9. 插件化开发—动态载入技术载入已安装和未安装的apk

    首先引入一个概念,动态载入技术是什么?为什么要引入动态载入?它有什么优点呢?首先要明确这几个问题.我们先从 应用程序入手,大家都知道在Android App中.一个应用程序dex文件的方法数最大不能超 ...

  10. hdu 4193 单调队列

    题意是给你n个数   组成的环   求以一个数开头 的数列全部前缀都为非负数的数列的个数: 思路:  先扩展成2*n的数列 然后求出sum[i]表示前i项的和     对每一个i>.=n结尾的数 ...