1. 为什么要用 Hibernate 缓存?

Hibernate是一个持久层框架,经常访问物理数据库。

为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。

缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。

2. 项目实战

当 Session 对象调用 save() 方法保存一个对象后,该对象会被放入到 Session 缓存中。

当 Session 对象调用 get() 或 load() 方法从数据库取出一个对象后,该对象也会被放入到 Session 缓存中。

当使用同一个 Session 编写 HQL 和 QBC 等从数据库中查询数据时,将直接从缓存中读取数据,不会访问数据库。

Hibernate 提供了几个方法(evit/clear/contains/flush....)来管理和判断一级缓存。

现 JavaEE Dao 层中,提供给外部的数据库访问,每次都会从 Session 工厂中获取新的 Session 线程 ,导致一级缓存很少被利用。

实例项目源码:https://git.oschina.net/LanboEx/hiberdemo

        //1.Hibernate 自身的一级缓存,可以查看到只输出了一条 sql
Session session = getSession();
UserPO userPO = session.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe");
System.out.println("1. 第一次访问 DB:" + userPO.getName() + "," + userPO.getPasswd()); UserPO userPO1 = session.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe");
System.out.println("2. 第二次访问 DB:" + userPO1.getName() + ",一级缓存中是否存在特定对象" + session.contains(userPO));

       //2.使用 evite/clear 方法手动清除缓存中特定对象,可以看到 hiber 输出了两条 SQL
Session session1 = getSession();
UserPO userPO3 = session1.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe");
System.out.println("3. 第一次获取对象:" + userPO3.getName() + "," + userPO3.getPasswd()); session1.evict(userPO3); UserPO userPO4 = session1.get(UserPO.class, "031e7a36972e11e6acede16e8241c0fe");
System.out.println("4. 第二次获取对象:" + userPO4.getName() + "," + userPO4.getPasswd());

3. Hibernate 缓存原理

Hibernate 缓存包括两大类:

a.Hibernate 一级缓存,又称为[Session的缓存]。

Session 内置不能被卸载,Session 的缓存是事务范围的缓存(Session 对象的生命周期通常对应一个数据库事务或者一个应用事务)。

一级缓存中,持久化类的每个实例都具有唯一的 OID。

b.Hibernate 二级缓存,又称为[SessionFactory的缓存]。

由于 SessionFactory 对象的生命周期和应用程序的整个过程对应。

Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。

第二级缓存是可选的,是一个可配置的插件,默认下 SessionFactory 不会启用这个插件。

Hibernate 提供了 org.hibernate.cache.CacheProvider 接口,它充当缓存插件与 Hibernate 之间的适配器。

什么样的数据适合存放到第二级缓存中?

1) 很少被修改的数据

2) 不是很重要的数据,允许出现偶尔并发的数据

3) 不会被并发访问的数据

4) 常量数据

不适合存放到第二级缓存的数据?

1) 经常被修改的数据

2) 绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发

3) 与其他应用共享的数据。

c.Session 的延迟加载实现要解决两个问题:正常关闭连接和确保请求中访问的是同一个 Session。

Hibernate Session 就是 java.sql.Connection 的一层高级封装,一个 Session 对应了一个 Connection。

Http 请求结束后正确的关闭 Session(过滤器实现了Session的正常关闭);

延迟加载必须保证是同一个 Session( Session 绑定在 ThreadLocal)。

d.Hibernate 查找对象如何应用缓存?

当 Hibernate 根据 ID 访问数据对象的时候,首先从 Session 一级缓存中查;

查不到,如果配置了二级缓存,那么从二级缓存中查;

如果都查不到,再查询数据库,把结果按照 ID 放入到缓存删除、更新、增加数据的时候,同时更新缓存。

e.一级缓存与二级缓存的对比图

一级缓存

二级缓存

存放数据的形式

相互关联的持久化对象

对象的散装数据

缓存的范围

事务范围,每个事务都拥有单独的一级缓存

进程范围或集群范围,缓存被同一个进程或集群范围内所有事务共享

并发访问策略

由于每个事务都拥有单独的一级缓存不会出现并发问题,因此无须提供并发访问策略

由于多个事务会同时访问二级缓存中的相同数据,因此必须提供适当的并发访问策略,来保证特定的事务隔离级别

数据过期策略

处于一级缓存中的对象永远不会过期,除非应用程序显示清空或者清空特定对象

必须提供数据过期策略,如基于内存的缓存中对象的最大数目,允许对象处于缓存中的最长时间,以及允许对象处于缓存中的最长空闲时间

物理介质

内存

内存和硬盘,对象的散装数据首先存放到基于内存的缓存中,当内存中对象的数目达到数据过期策略的maxElementsInMemory值,就会把其余的对象写入基于硬盘的缓存中

缓存软件实现

在Hibernate的Session的实现中包含

由第三方提供,Hibernate仅提供了缓存适配器,用于把特定的缓存插件集成到Hibernate中

启用缓存的方式

只要通过Session接口来执行保存,更新,删除,加载,查询,Hibernate就会启用一级缓存,对于批量操作,如不希望启用一级缓存,直接通过JDBCAPI来执行

用户可以再单个类或类的单个集合的粒度上配置第二级缓存,如果类的实例被经常读,但很少被修改,就可以考虑使用二级缓存,只有为某个类或集合配置了二级缓存,Hibernate在运行时才会把它的实例加入到二级缓存中

用户管理缓存的方式

一级缓存的物理介质为内存,由于内存的容量有限,必须通过恰当的检索策略和检索方式来限制加载对象的数目,Session的evit()方法可以显示的清空缓存中特定对象,但不推荐

二级缓存的物理介质可以使内存和硬盘,因此第二级缓存可以存放大容量的数据,数据过期策略的maxElementsInMemory属性可以控制内存中的对象数目,管理二级缓存主要包括两个方面:选择需要使用第二级缓存的持久化类,设置合适的并发访问策略;选择缓存适配器,设置合适的数据过期策略。SessionFactory的evit()方法也可以显示的清空缓存中特定对象,但不推荐

Hibernate 缓存机制浅析的更多相关文章

  1. 10.hibernate缓存机制详细分析(转自xiaoluo501395377)

    hibernate缓存机制详细分析   在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级别).二级缓存(sessionFactory级别)以及查询缓存,当然还要讨论 ...

  2. 【转 :Hibernate 缓存机制】

    转自:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html Hibernate 缓存机制 一.why(为什么要用Hibernate缓存 ...

  3. hibernate缓存机制详解

    hiberante面试题—hibernate缓存机制详解   这是面试中经常问到的一个问题,可以按照我的思路回答,准你回答得很完美.首先说下Hibernate缓存的作用(即为什么要用缓存机制),然后再 ...

  4. hibernate缓存机制与N+1问题

    在项目中遇到的趣事 本文基于hibernate缓存机制与N+1问题展开思考, 先介绍何为N+1问题 再hibernate中用list()获得对象: /** * 此时会发出一条sql,将30个学生全部查 ...

  5. hibernate缓存机制(转)

    原文出处:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html 一.why(为什么要用Hibernate缓存?) Hibernate是 ...

  6. hibernate缓存机制详细分析 复制代码 内部资料 请勿转载 谢谢合作

    您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...

  7. Hibernate 缓存机制

    一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...

  8. hibernate缓存机制详细分析

    转自:http://www.cnblogs.com/xiaoluo501395377/p/3377604.html 在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级 ...

  9. Hibernate 缓存机制二(转)

    感谢:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html 一.why(为什么要用Hibernate缓存?) Hibernate是一个 ...

随机推荐

  1. 匹夫细说C#:委托的简化语法,聊聊匿名方法和闭包

    0x00 前言 通过上一篇博客<匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的>的内容,我们实现了使用委托来构建我们自己的消息系统的过程.但是在日常的开发中,仍然有很多开发者因为 ...

  2. CSS知识总结(六)

    CSS常用样式 4.段落样式 1)行高 控制段落内每行高度 line-height : normal | length 例子 源代码: /* CSS代码 */ .normal{ line-height ...

  3. Linux网络相关配置

    一.修改网卡相关配置 Linux网络参数是在/etc/sysconfig/network-scripts/ifcfg-eth0中设置,其中ifcfg-eth0表示是第一个网卡,如果还有另外一块网卡,则 ...

  4. C#调用SendMessage 用法

    函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.该函数是应用程序和应用程序之间进行消息传递的主要手段之一.    函数原型:LRESUL ...

  5. [Oracle] Bulk Insert Data

    命名空间:Oracle.DataAccess.Client 组件:Oracle.DataAccess.dll(2.112.1.0) ODP.NET 版本:ODP.NET for .NET Framew ...

  6. html

    有目标的学知识才行 要学习html语言,我突然发现我好像可以在markdown文本编辑器中编辑html标签,既然这样我就多玩玩.markdown完全兼容html,这真的是一个好事情.好像也有功能在ma ...

  7. [dedecms]后台不显示验证码

    原因:某个加载文件的开始处有一个标点,去掉就可显示 // 文件地址 /include/vdimgck.php @session_start(); $_SESSION['securimage_code_ ...

  8. 理解RESTful架构

    越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高 ...

  9. Maven创建web项目:SpringMVC+Mybatis 【转】

    IDEA14创建Maven管理的SpringMVC+Mybatis,web项目 项目构建步骤 1.File->New->Project 勾选Create from archetype 点击 ...

  10. 分析js中的constructor 和prototype

    在javascript的使用过程中,constructor 和prototype这两个概念是相当重要的,深入的理解这两个概念对理解js的一些核心概念非常的重要. 我们在定义函数的时候,函数定义的时候函 ...