我们知道hibernate的一级缓存是将数据缓存到了session中从而降低与数据库的交互。那么二级缓存呢?

一、应用场合

比方。在12306购票时。须要选择出发地与目的地,假设每点一次都与数据库交互一次,这就非常不合适,这些地点数据在相当长的一段时间内是不会发生变化的(山东省在相当长的时间内还叫山东省),所以应该缓存起来,不是必需每次都与数据库交互,并且该类数据安全性也不是非常高。

适合二级缓存的数据:

在现代软件开发中。确实存在一类数据没有什么私有性,为公开的数据,数据基本上不发生变化,该数据保密性不是非常强,但又会常常被用到(比方火车票上的出发地与目的地数据)。

注意:假设一个数据一直在改变,不适合用缓存。

流式数据:数据时时刻刻在变的数据,比方手机应用获取手机所在地,后台的推送系统,发出一些信息。比方短信会提示你某天夜间流量超过多少。建议购买夜间流量。而这类数据适合使用strom来处理 。

二、生命周期

二级缓存为sessionFactory级别的缓存,其生命周期和sessionFactory是一致的,Hibernate启动后就有了.

二级缓存在Hibernate中的位置

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

所以Hibernate内部并没有实现二级缓存,而是应用第三方插件来实现二级缓存的。

三、二级缓存的设置

利用的是ehcache实现的二级缓存

1.加入ehcache所需的jar包

2.在hibernate的配置文件里进行配置

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

四、二级缓存的操作

哪些方法能够把对象放入到二级缓存中?

get方法,list方法能够把一个或者一些对象放入到二级缓存中

哪些方法能够把对象从二级缓存中提取出来?

get方法,iterator方法能够提取

注意:用的时候一定要小心使用各方法,取数据时。假设把list用成iterate会造成效率的及其减少

五、二级缓存的存储策略

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

read-only:对象仅仅要载入到二级缓存以后,就仅仅能读取,不能改动。

read-write:对二级缓存中的对象可以进行读和写的操作

注意:一般都设置为read-only

缓存得到磁盘

假设一个系统的权限特别大。这就不适合长时间的放入到二级缓存中,会导致占用内存逐渐变大。查询效率逐渐减少,这样的情况能够二级缓存移到磁盘上,可是在现代开发假设须要缓存较多。一般都是使用分布式缓存。



測试:

hibernate.cfg.xml

<?

xml version='1.0' encoding='utf-8'?

>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration> <session-factory> <property name="hibernate.dialect"><![CDATA[org.hibernate.dialect.MySQLDialect]]></property>
<property name="hibernate.connection.driver_class"><![CDATA[com.mysql.jdbc.Driver]]></property>
<property name="hibernate.connection.url"><![CDATA[jdbc:mysql:///hibernate1]]></property>
<property name="hibernate.connection.username"><![CDATA[root]]></property>
<property name="hibernate.connection.password"><![CDATA[qiaolezi]]></property> <property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.min_size">10</property>
<property name="hibernate.c3p0.max_statements">10</property>
<property name="hibernate.c3p0.acquire_increment">5</property>
<property name="hibernate.c3p0.timeout">3000</property> <!-- 二级缓存供应商 -->
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- 开启二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 开启二级缓存的统计机制 -->
<property name="generate_statistics">true</property> <property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
<property name="format_sql">true</property> <mapping resource="cn/cil/domain/Classes.hbm.xml" />
<mapping resource="cn/cil/domain/Student.hbm.xml" /> </session-factory>
</hibernate-configuration>

Classes

public class Classes implements Serializable{

	private Long cid;
private String name;
private Set<Student> students;
}

Classes.hbm.xml

<class name="Classes" table="CLASSES">
<cache usage="read-write"/><!-- 仅仅读 -->
<id name="cid">
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="students" cascade="save-update" inverse="true">
<cache usage="read-only"/><!-- 设置集合的二级缓存 -->
<!-- key:外键,告诉hibernate通过cid来建立classes与student的关系 -->
<key column="cid"></key>
<one-to-many class="Student"/>
</set>
</class>

Student

public class Student implements Serializable{

	private Long sid;
private String name;
private Classes classes;
}

Student.hbm.xml

<class name="Student" table="STUDENT">
<id name="sid">
<generator class="native"></generator>
</id>
<property name="name"></property> <many-to-one cascade="save-update" name="classes" column="cid" class="Classes">
</many-to-one>
</class>

測试类

public class SessionFactoryCacheTest {

	private Session session;
private Transaction transaction;
private SessionFactory sessionFactory; /**
* 測试get,在session关闭后,再次请求,不发出sql
* 该方法在取数据时,先从一级缓存中找,假设二级缓存开启了,接下来就会从二级缓存中,都没有,则查数据库
* 在DefaultLoadEventListener.class中能够清晰的看到
* 440行: 从一级缓存,459 行: 从二级缓存,477行: 从数据库
*
* get能够把对象放入二级缓存,也能够从二级缓存中取数据
*/
@Test
public void testGet(){ sessionFactory = HibernateUtils.getSessionFactory();
session = HibernateUtils.openSession();
Classes classes = (Classes) session.get(Classes.class, 1L);
System.out.println(sessionFactory.getStatistics()
.getEntityLoadCount());//1
session.close();
session = HibernateUtils.openSession();
classes = (Classes) session.get(Classes.class, 1L);//不发出sql
session.close();
}
/**
* Hibernate提供了二级缓存的统计机制
* save不能把对象存入二级缓存
*/
@Test
public void testSave(){
sessionFactory = HibernateUtils.getSessionFactory();
session = HibernateUtils.openSession();
transaction = session.beginTransaction();
Classes classes = new Classes();
classes.setName("a");
session.save(classes);
System.out.println(sessionFactory.getStatistics()
.getEntityLoadCount());//0
transaction.commit();
session.close();
} /**
* session.update不操作二级缓存
*/
@Test
public void testUpdate(){
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Classes classes = new Classes();
classes.setCid(3L);
classes.setName("afds");
session.update(classes);
System.out.println(sessionFactory.getStatistics()
.getEntityInsertCount());//0
transaction.commit();//会报错,可是不影响,设置为<cache usage="read-write">,假设集合也设置了二级缓存,那集合也要设置为相同
session.close();
} /**
* HQL中的list,能够把对象放入到二级缓存,可是不能从二级缓存取数据
*/
@Test
public void testQueryList(){
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession(); session.createQuery("from Classes").list();
System.out.println(sessionFactory.getStatistics()
.getEntityLoadCount());//不是0
session.close();
session = sessionFactory.openSession();
session.createQuery("from Classes").list();//发出sql,由于getEntityLoadCount不为0,所以list()能够把对象放入二级缓存,可是不能从二级缓存中取对象
session.close();
} /**
* iterator,能够从二级缓存中取数据
* iterate方法的查询策略:
* 先查找该表中全部的id值
* 再依据id值从二级缓存中查找对象,假设有,则利用二级缓存,
* 假设没有,则依据id查询全部属性的值
*/ @Test
public void testQueryIterate(){
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
session.createQuery("from Classes").list(); System.out.println(sessionFactory.getStatistics()
.getEntityLoadCount());//不是0
session.close();
session = sessionFactory.openSession();
Iterator<Classes> iterator = session.createQuery("from Classes").iterate();
while (iterator.hasNext()) {
Classes classes = (Classes) iterator.next();
System.out.println(classes.getName());
} session.close();
} /**
* 集合的二级缓存,须要在hbm.xml文件里进行对应的设置
* 集合有一级缓存也有二级缓存
*/
@Test
public void testCollection(){
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession(); Classes classes = (Classes) session.get(Classes.class, 1L);
Set<Student> students = classes.getStudents();
for(Student student : students){
System.out.println(student.getName());
}
System.out.println(sessionFactory.getStatistics()
.getCollectionLoadCount());//1
session.close();
} /**
* 二级缓存 到 磁盘
*/
@Test
public void testCacheDisk(){
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession(); session.createQuery("from Classes").list();
try {
Thread.sleep(2000L);//停一会,否则写不进去数据
} catch (Exception e) { e.printStackTrace();
}
session.close();
}
}

二级缓存企业应用的不多,实在有些鸡肋

Hibernate学习笔记(六) — Hibernate的二级缓存的更多相关文章

  1. hibernate学习笔记之四 Hibernate的增删改查

    采用JUnit测试,继承TestCase import java.util.Date; import junit.framework.TestCase; import org.hibernate.Se ...

  2. hibernate学习笔记之一 hibernate简介

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架 hibernate可以自动生成SQL语句,自 ...

  3. Hibernate学习11——配置Hibernate二级缓存

    一.缓存的概念: 以空间换时间:   二.Hibernate缓存的分类: 前面我们讲的缓存都是session缓存:也叫一级缓存:get,load等缓存都是内置的,一级缓存: SessionFactor ...

  4. Hibernate学习笔记(二)

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

  5. Hibernate学习笔记(一)

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

  6. Hibernate 学习笔记一

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

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

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

  8. Hibernate查询、连接池、二级缓存

    Hibernate第三天: 1. 对象状态 2. session缓存 3. lazy懒加载 4. 映射 一对一对映射 组件/继承映射 目标: 一.hibernate查询 二.hibernate对连接池 ...

  9. Hibernate第十二篇【二级缓存介绍、缓存策略、查询缓存、集合缓存】

    Hibernate二级缓存介绍 前面我们已经讲解过了一级缓存,一级缓存也就是Session缓存,只在Session的范围内有效-作用时间就在Session的作用域中,范围比较小 Hibernate为我 ...

随机推荐

  1. C# 實現文件壓縮-- 背景:服務器Log.txt 過多,佔用過多硬盤空間,壓縮備份后節省空間資源

    1.壓縮實現代碼如下: 調用ICSharpCode.SharpZipLib.dll(free software,可以搜到源碼). 轉移指定目錄文件夾轉移到目標文件夾 壓縮目標文件夾 刪除目標文件夾 u ...

  2. 类的封装,property特性,类与对象的绑定方法和非绑定方法,

    类的封装 就是把数据或者方法封装起来 为什么要封装 封装数据的主要原因是:保护隐私 封装方法的主要原因是:隔离复杂度(快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了,比如你 ...

  3. 计算机内存数据存储基本原理----寄存器和RAM的电路基础

    计算机里存储数据主要有这几个部件:CPU里的寄存器和缓存.内存(内存条)和磁盘,这里我们主要简单讲下寄存器和内存条的基础实现电路. 在前面的文章<CPU怎么计算1+1----CPU计算的电路基础 ...

  4. JavaSE-05 数组

    学习要点 数组的基本用法 数组的典型应用 数组相关概念 问题 Java考试结束后,老师给小强分配了一项任务,让他计算全班(30人)的平均分,按照目前的知识结构,如何实现? 问题分析 数组 定义:数组是 ...

  5. Android 控件布局常用的属性

    <!--单个控件经常用到android:id —— 为控件指定相应的IDandroid:text —— 指定控件当中显示的文字,需要注意的是,这里尽量使用strings.xml文件当中的字符串a ...

  6. Mybatis的一级二级缓存

    Mybatis提供了缓存机制,可以减轻数据库的压力,提高性能 Mybatis的缓存分为两级:一个是一级缓存,一个二级缓存 一级缓存:即默认使用的缓存SqlSession级别的缓存,只在sqlsessi ...

  7. ERC20 Token

    pragma solidity ^0.4.8; contract Token{ // token总量,默认会为public变量生成一个getter函数接口,名称为totalSupply(). uint ...

  8. [Python3网络爬虫开发实战] 1.2.3-ChromeDriver的安装

    前面我们成功安装好了Selenium库,但是它是一个自动化测试工具,需要浏览器来配合使用,本节中我们就介绍一下Chrome浏览器及ChromeDriver驱动的配置. 首先,下载Chrome浏览器,方 ...

  9. LeetCode(47)Permutations II

    题目 Given a collection of numbers that might contain duplicates, return all possible unique permutati ...

  10. mat 服务器分析大堆,本地打开

    1:服务器执行nohup sh /usr/local/mat/ParseHeapDump.sh es9.bin org.eclipse.mat.api:suspects org.eclipse.mat ...