一、一级缓存

一级缓存又称为“Session缓存”或者“会话级缓存”,通过Session从数据库查询实体时,会把实体在内存中存储起来,下一次查询同一实体时不再再次执行sql语句查询数据库,而是从内存中获取。一级缓存的生命周期和Session相同。一级缓存是无法取消的。

1.一级缓存中的数据可适用范围在当前会话之类,例如用同一个session查询两次user表和同两个session查询俩次user表,查询数据库的次数是不一样的。首先,像这样查询两次,可以看见打印的sql语句只有一次,因为第二次是直接从当前session缓存中取的。

但是把注释去掉,就会发现,sql打印了两次,因为他执行了两次数据库的查询操作。

    /**
* 一级缓存
*/
@Test
public void cacheTest() {
Tb_User u = session.get(Tb_User.class, "1");
System.out.println(u.getName());
//session = sessionFactory.openSession();
u = session.get(Tb_User.class, "1");
System.out.println(u.getName());
}

2.evict 、clear

evict方法:清除一级缓存中的指定对象;

clear方法:清除一级缓存的所有对象。

这段代码打印的sql语句打印了两次,结果很明显。

  @Test
public void cacheTest() {
Tb_User u = session.get(Tb_User.class, "1"); //清除一级缓存中的指定对象
//session.evict(u); //清楚一级缓存中的所有对象
session.clear(); u = session.get(Tb_User.class, "1");
}

3.query.list | query.getResultList

这两个方法是一样的,但是现在我看提示说query.list是废弃的。他们都不使用缓存,执行下面这段代码,可以很明确的看见打印了两次sql,这两个方法都是不使用缓存的,但是会把查询出来的数据存入缓存中。

    /**
* 一级缓存
*/
@Test
public void cacheTest() { Query query = session.createQuery("From Tb_User");
List<Tb_User> list = query.getResultList();
for(Tb_User u : list){
System.out.println(u.getName());
} list = query.getResultList();
for(Tb_User u : list){
System.out.println(u.getName());
} }

4.query.iterate()

若用迭代器Iterator,从打印的sql来看,他只查询了id,然后还是打印了Name,因为query.iterate()用到了缓存,他也会把查询出来的数据存入缓存中。

    /**
* 一级缓存
*/
@Test
public void cacheTest() { Query query = session.createQuery("From Tb_User");
List<Tb_User> list = query.getResultList();
for(Tb_User u : list){
System.out.println(u.getName());
} Iterator it = query.iterate();
while(it.hasNext()){
Tb_User u = (Tb_User)it.next();
System.out.println(u.getName());
} }

query.iterate()怎么使用缓存?

把代码query.getResultList()相关的几行注释掉,执行后,可以看见打印的sql语句,先查询了id,然后根据id用where去数据挨着查询出来,我的数据库里有3条数据,所有一共查询了4次数据库。

query.iterator会先去查询数据库中的id,然后根据id,先在缓存中查找是否有相应的数据,有则直接用,没有则从数据库中找。

解释下前面的代码结果:

若query.iterator遍历方法之前执行了list方法,list方法查询出来的数据被缓存了,但list方法不使用缓存,因此再次执行list时会重新查询数据库,而iterator方法只从数据库查询id,这时每个id在内存中都有对应的值,所以Name属性是从内存中取出来的。

若query.iterator遍历方法之前没有执行了list方法,那么此时数据并没有缓存在内存中,那么iterator方法依然会先查询id,在遍历时,发现内存中根据id找不到该数据,于是就发送sql到数据库中找,此时Name属性就是真的从数据库中现场查找出来的了。

若query.iterator遍历方法之前执行了query.iterator遍历方法,那么结果和第一种情况类似,他会先依次在数据库中查找,缓存到内存,然后第二次执行时,只查找了id值,其余的在内存中找到。

    @Test
public void cacheTest() { Query query = session.createQuery("From Tb_User");
// List<Tb_User> list = query.getResultList();
// for(Tb_User u : list){
// System.out.println(u.getName());
// } Iterator it = query.iterate();
while(it.hasNext()){
Tb_User u = (Tb_User)it.next();
System.out.println(u.getName());
} // it = query.iterate();
// while(it.hasNext()){
// Tb_User u = (Tb_User)it.next();
// System.out.println(u.getName());
// }
}

二、二级缓存

hibernate的二级缓存又称为“全局缓存”,“应用级缓存”,二级缓存中的数据可适用方位是当前应用的所有会话,不随session关闭而关闭,他是可插拔式的缓存。二级缓存需要其他的jar包,自己去配置。配置步骤:

①.添加二级缓存对应的jar包

jar包在 \hibernate-release-5.2.1.Final\lib\optional\ehcache 中有三个ehcache-2.10.1.jar,hibernate-ehcache-5.2.1.Final.jar,slf4j-api-1.7.7.jar都需要添加进去

②.在hibernate的配置文件中添加Provider类的描述,即hibernate.cfg.xml中 添加属性

        <!-- 开启二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- 配置RegionFactory为Ehcache的RegionFactory -->
<property name="cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>

③.添加二级缓存的属性配置文件

在 \hibernate-release-5.2.1.Final\project\hibernate-ehcache\src\test\resources 目录下,可以找到ehcache.xml的配置文件,复制粘贴到hibernate.cfg.xml统一目录下,打开xml文件看到这么一段,注释写得很清楚,每个属性干嘛的。这个配置是默认的缓存策略。

    <!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager. The following attributes are required for defaultCache: maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element beforeQuery it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element beforeQuery it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit. -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>

④.在需要被缓存的表所对应的映射文件中添加<cache />标签,作为class的子节点。usage属性表示的是事务模式,还有include属性,设置是否加载延迟加载的属性,region属性是Ehcache配置中,可以为表单独增加缓存策略,否则全部都是默认策略。

<cache usage="read-only" region="Tb_User"/>

若需要单独配置缓存策略,需要在ehcache.xml中加上一段,表示Tb_User使用当前的缓存策略,不用默认的。(不是必须配置的)

<cache name="Tb_User" maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" />

此时基本的配置就完成了,依然用第一个例子做测试

    /**
* 一级缓存
*/
@Test
public void cacheTest() {
Tb_User u = session.get(Tb_User.class, "1");
System.out.println(u.getName());
//session = sessionFactory.openSession();
u = session.get(Tb_User.class, "1");
System.out.println(u.getName());
}

此时,无论是否打开一个新的session,都只会打印一条sql语句,若把cache.use_second_level_cache 属性值设为false,那么就可以关闭二级缓存。

三、一级缓存和二级缓存比较

补充:在映射文件中的cache标签的usage有四种属性

read-only: 对于永远不会被修改的数据可以采用这种并发访问策略,它的并发性能是最高的。但必须保证数据不会被修改,否则就会出错,使用场景可以是OA系统中比较常用的字典表/枚举表
nonstrict-read-write: 非严格读写不能保证缓存与数据库中数据的一致性,如果存在两个事务并发地访问缓存数据的可能,则应该为该数据配置一个很短的过期时间,以减少读脏数据的可能。对于极少被修改,并且可以容忍偶尔脏读的数据可以采用这种并发策略。
read-write: 对于经常被读但很少修改的数据可以采用这种策略,它可以防止读脏数据。
transactional:它可以防止脏读和不可重复读这类的并发问题。

transactional策略是事务隔离级别最高,read-only的隔离级别最低。事务隔离级别越高,并发性能就越低。

Hibernate学习笔记--------3.缓存的更多相关文章

  1. Hibernate学习笔记(二)

    2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...

  2. Hibernate学习笔记(一)

    2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...

  3. Hibernate 学习笔记一

    Hibernate 学习笔记一 今天学习了hibernate的一点入门知识,主要是配置domain对象和表的关系映射,hibernate的一些常用的配置,以及对应的一个向数据库插入数据的小例子.期间碰 ...

  4. Hibernate学习笔记-Hibernate HQL查询

    Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...

  5. Hibernate学习笔记(二)—— 实体规则&对象的状态&一级缓存

    一.持久化类 1.1 什么是持久化类? Hibernate是持久层的ORM映射框架,专注于数据的持久化工作.所谓的持久化,就是将内存中的数据永久存储到关系型数据库中.那么知道了什么是持久化,什么又是持 ...

  6. HIbernate学习笔记(八) hibernate缓存机制

    hibernate缓存 一. Session级缓存(一级缓存) 一级缓存很短和session的生命周期一致,因此也叫session级缓存或事务级缓存 hibernate一级缓存 那些方法支持一级缓存: ...

  7. Hibernate学习笔记二:Hibernate缓存策略详解

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

  8. Hibernate学习笔记(六) — Hibernate的二级缓存

    我们知道hibernate的一级缓存是将数据缓存到了session中从而降低与数据库的交互.那么二级缓存呢? 一.应用场合 比方.在12306购票时.须要选择出发地与目的地,假设每点一次都与数据库交互 ...

  9. Hibernate学习笔记

    一.Hibernate基础 1.Hibernate简介 Hibernate是一种对象关系映射(ORM)框架,是实现持久化存储的一种解决方案.Java包括Java类到数据库表的映射和数据查询及获取的方法 ...

随机推荐

  1. 关于java环境配置的问题

    在以前刚开始接触Java环境配置问题的时候,配置了一大串的字符串,所有的路径全部在一个path变量里面,特别冗杂. 由于这两天重新再装了一个版本的JDK结果出现毛病了,就只有重新配置该环境变量,结果又 ...

  2. Eclipse(非J2EE版本)配置Extjs环境以及安装部署Tomcat

    Eclipse(非J2EE版本)配置Extjs环境(Spket) 1. 安装spket插件,帮助->安装新软件->http://www.agpad.com/update. 2. 设置Spk ...

  3. Bnuoj-29359 Deal with numbers 线段树

    题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=29359 题意:一个数列,有三种操作: 1.区间[a,b]之间大于零的数整出c. 2.区间[ ...

  4. Java HashMap 源码解析

    今天正式开始分析具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 签名(signature) public class HashMap<K,V> extends Abstract ...

  5. python 安装第三方模块

    在Python中,安装第三方模块,是通过setuptools这个工具完成的. 如果你正在使用Mac或Linux,安装setuptools本身这个步骤就可以跳过了. 如果你正在使用Windows,请首先 ...

  6. sts中从svn导入maven项目

    1.创建资源库 2.导入项目作为本地项目 3.将子module从本地导入(默认情况下,只会将主pom所在的工程导入)

  7. Swift 基本语法1

    一.Swift简介 2010年的夏天,苹果公司的开发人员Chris Lattne接到了一个特别的任务,为OS X 和iOS平台开发下一代的编程语言,也就是Swift. 苹果公司于2014年WWDC(苹 ...

  8. 曾经的pc端项目踩到的一些兼容性的坑及其解决方案

    曾经公司pc端项目一直最低兼容到IE7,要求和chrome下浏览效果一致,真心坑坏了我和另外一个小伙伴(另一个小伙伴以前也没处理过兼容问题).不过还好,在这里真心感谢鑫哥博客的详解,从底层原理讲到了具 ...

  9. MSSQL 如何实现 MySQL 的 limit 查询方式 (转)

    不知为何,MSSQL 中没有 limit 这个极为重要的查询方式,熟悉 MySQL 的朋友都知道,MySQL 的 limit 对于实现分页和一些限制结果集的应用中非常方便.没有不要紧,我们可以用其他方 ...

  10. Codeforces Round #200 (Div. 1)A. Rational Resistance 数学

    A. Rational Resistance Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/343 ...