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. docker进入后台运行的容器

    转载请注明出处   我们运行docker容器的时候,使用了-d参数,把容器在后台运行后. 这个时候,我们使用docker ps命令,我们就可以知道哪些程序在后台运行.   我们要怎么进入到docker ...

  2. Rafy 框架 - 使用 SqlTree 查询

    本文介绍如何使用 Rafy 框架中的 Sql Tree 查询: 除了开发者常用的 Linq 查询,Rafy 框架还提供了 Sql 语法树的方式来进行查询. 这种查询方式下,开发者不需要直接编写真正的 ...

  3. Node学习笔记(四):gulp+express+io.socket部署angularJs2(填坑篇)

    这篇就先暂停下上篇博客--你画我猜的进度,因为在做这个游戏的时候,想采用最新的ng2技术,奈何坑是一片又一片,这边就先介绍下环境部署和填坑史 既然要用ng2,首先要拿到资源,我这边用的是angular ...

  4. 『.NET Core CLI工具文档』(六)dotnet 命令

    说明:本文是个人翻译文章,由于个人水平有限,有不对的地方请大家帮忙更正. 原文:dotnet command 翻译:dotnet 命令 名称 dotnet -- 运行命令行命令的一般驱动程序 概要 d ...

  5. session的使用方法详解

    session的使用方法详解 Session是什么呢?简单来说就是服务器给客户端的一个编号.当一台WWW服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站.当每个用户首次与这台WWW服务器 ...

  6. bzoj1878--离线+树状数组

    这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...

  7. Delphi_05_Delphi_Object_Pascal_基本语法_03

    继续Delphi的学习之旅, 废话不多说,直接贴代码. { Delphi基本语法 1.对象 2.指针 3.类型别名 和 类型转换 } program DelphiObject; {$APPTYPE C ...

  8. jQuery获取短信验证码+倒计时实现

    jQuery 短信验证码倒计时 <script type="text/javascript" charset="utf-8"> $(function ...

  9. html5上传图片(一)一跨域上传

    最近开发一个上传图片的模块,传图片的接口不支持跨域上传,并且只支持单张上传,而我们的产品要求要实现多张上传.我搞了一个代理页面,先将图片传到代理页面,然后再通过代理页面传到上传图片接口.虽然这种方式经 ...

  10. Apache Spark 1.6 Hadoop 2.6 Mac下单机安装配置

    一. 下载资料 1. JDK 1.6 + 2. Scala 2.10.4 3. Hadoop 2.6.4 4. Spark 1.6 二.预先安装 1. 安装JDK 2. 安装Scala 2.10.4 ...