hibernate缓存

一、 Session级缓存(一级缓存)

一级缓存很短和session的生命周期一致,因此也叫session级缓存或事务级缓存

hibernate一级缓存

那些方法支持一级缓存:

* get()

* load()

* iterate(查询实体对象)

如何管理一级缓存:

*session.clear(),session.evict()

如何避免一次性大量的实体数据入库导致内存溢出

* 先flush,再clear

如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足要求可以考虑采用数据本身的特定导入工具

二、 二级缓存

Hibernate默认的二级缓存是开启的。

二级缓存也称为进程级的缓存,也可称为SessionFactory级的缓存(因为SessionFactory可以管理二级缓存),它与session级缓存不一样,一级缓存只要session关闭缓存就不存在了。而二级缓存则只要进程在二级缓存就可用。

二级缓存可以被所有的session共享

二级缓存的生命周期和SessionFactory的生命周期一样,SessionFactory可以管理二级缓存

二级缓存同session级缓存一样,只缓存实体对象,普通属性的查询不会缓存

二级缓存一般使用第三方的产品,如EHCache

1、   二级缓存的配置和使用:

配置二级缓存的配置文件:模板文件位于hibernate\etc目录下(如ehcache.xml),将模板存放在ClassPath目录中,一般放在根目录下(src目录下)

<ehcache>

<!-- 设置当缓存对象益出时,对象保存到磁盘时的保存路径。

   如 d:\xxxx

The following properties aretranslated:

user.home - User's home directory

user.dir - User's current workingdirectory

java.io.tmpdir - windows的临时目录 -->

<diskStore path="java.io.tmpdir"/>

<!--默认配置/或对某一个类进行管理

maxInMemory       - 缓存中可以存入的最多个对象数

eternal           - true:表示永不失效,false:不是永久有效的。

timeToIdleSeconds - 空闲时间,当第一次访问后在空闲时间内没有访问,则对象失效,单位为秒

timeToLiveSeconds - 被缓存的对象有效的生命时间,单位为秒

overflowToDisk  当缓存中对象数超过核定数(益出时)时,对象是否保存到磁盘上。true:保存;false:不保存

如果保存,则保存路径在标签<diskStore>中属性path指定

-->

<defaultCache

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

/>

</ehcache>

2、   二级缓存的开启:

Hibernate中二级缓存默认就是开启的,也可以显示的开启

二级缓存是hibernate的配置文件设置如下:

<!--开启二级缓存,hibernate默认的二级缓存就是开启的 -->

<property name="hibernate.cache.use_second_level_cache">true</property>

3、   指定二级缓存产品提供商:

修改hibernate的 配置文件,指定二级缓存提供商,如下:

<!--指定二级缓存提供商-->

<property name="hibernate.cache.provider_class">

org.hibernate.cache.EhCacheProvider

</property>

以下为常见缓存提供商:

Cache

Provider class

Type

Cluster Safe

Query Cache Supported

Hashtable (not intended for production use)

org.hibernate.cache.HashtableCacheProvider

memory

yes

EHCache

org.hibernate.cache.EhCacheProvider

memory, disk

yes

OSCache

org.hibernate.cache.OSCacheProvider

memory, disk

yes

SwarmCache

org.hibernate.cache.SwarmCacheProvider

clustered (ip multicast)

yes (clustered invalidation)

JBoss TreeCache

org.hibernate.cache.TreeCacheProvider

clustered (ip multicast), transactional

yes (replication)

yes (clock sync req.)

4、   使用二级缓存

a)       xml方式:指定哪些实体类使用二级缓存:

方法一:在实体类映射文件中,使用<cache>来指定那个实体类使用二级缓存,如下:

<cache 
    usage="transactional|read-write|nonstrict-read-write|read-only"  (1)
    region="RegionName"                                              (2)
    include="all|non-lazy"                                           (3)
/>

(1)   usage(必须)说明了缓存的策略: transactional、 read-writenonstrict-read-write或 read-only

(2)   region (可选, 默认为类或者集合的名字(class orcollection role name)) 指定第二级缓存的区域名(name of the secondlevel cache region)

(3)   include (可选,默认为 allnon-lazy 当属性级延迟抓取打开时, 标记为lazy="true"的实体的属性可能无法被缓存

另外(首选?), 你可以在hibernate.cfg.xml中指定<class-cache>和 <collection-cache> 元素。

这里的usage 属性指明了缓存并发策略(cache concurrency strategy)

策略:只读缓存(Strategy:read only)

如果你的应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读 缓存。这是最简单,也是实用性最好的方法。甚至在集群中,它也能完美地运作。

<class name="eg.Immutable" mutable="false">
    <cache usage="read-only"/>
    ....
</class>

策略:读/写缓存(Strategy:read/write)

如果应用程序需要更新数据,那么使用/写缓存 比较合适。 如果应用程序要求“序列化事务”的隔离级别(serializable transaction isolation level),那么就决不能使用这种缓存策略。 如果在JTA环境中使用缓存,你必须指定hibernate.transaction.manager_lookup_class属性的值, 通过它,Hibernate才能知道该应用程序中JTA的TransactionManager的具体策略。 在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前, 整个事务已经结束。 如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate内置的缓存策略并不支持锁定功能。

<class name="eg.Cat" .... >
    <cache usage="read-write"/>
    ....
    <set name="kittens" ... >
        <cache usage="read-write"/>
        ....
    </set>
</class>

策略:非严格读/写缓存(Strategy: nonstrictread/write)

如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。如果在JTA环境中使用该策略,你必须为其指定hibernate.transaction.manager_lookup_class属性的值, 在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前, 整个事务已经结束。

策略:事务缓存(transactional)

Hibernate的事务缓存策略提供了全事务的缓存支持, 例如对JBoss TreeCache的支持。这样的缓存只能用于JTA环境中,你必须指定为其hibernate.transaction.manager_lookup_class属性。

没有一种缓存提供商能够支持上列的所有缓存并发策略。下表中列出了各种提供器、及其各自适用的并发策略。

表 19.2.  各种缓存提供商对缓存并发策略的支持情况(Cache Concurrency Strategy Support)

Cache

read-only

nonstrict-read-write

read-write

transactional

Hashtable (not intended for production use)

yes

yes

yes

EHCache

yes

yes

yes

OSCache

yes

yes

yes

SwarmCache

yes

yes

JBoss TreeCache

yes

yes

注:此方法要求:必须要标签<cache>放在<id>标签之前

 

<class name="com.wjt276.hibernate.Student"table="t_student">

<!--  指定实体类使用二级缓存 -->

<cache usage="read-only"/>//***********

<id name="id"column="id">

<generator class="native"/>

</id>

<property name="name"column="name"/>

<!--

使用多对一标签映射 一对多双向,下列的column值必需与多的一端的key字段值一样。

-->

<many-to-one name="classes"column="classesid"/>

</class>

方法二:在hibernate配置文件(hibernate.cfg.xml)使用<class-cache>标签中指定

要求:<class-cache>标签必须放在<maping>标签之后。

<hibernate-configuration>

<session-factory>

…………

<mapping resource="com/wjt276/hibernate/Classes.hbm.xml"/>

<mapping resource="com/wjt276/hibernate/Student.hbm.xml"/>

<class-cache class="com.wjt276.hibernate.Student"usage="read-only"/>

</session-factory>

</hibernate-configuration>

一般推荐使用方法一。

b)       annotation注解

为了优化数据库访问,你可以激活所谓的Hibernate二级缓存.该缓存是可以按每个实体和集合进行配置的.

@org.hibernate.annotations.Cache定义了缓存策略及给定的二级缓存的范围. 此注解适用于根实体(非子实体),还有集合.

@Entity

@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

publicclass Forest { ... }

@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)

@JoinColumn(name="CUST_ID")

@Cache(usage =CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

public SortedSet<Ticket> getTickets(){

return tickets;

}

@Cache(

CacheConcurrencyStrategy usage();                 (1)

String region() default "";                       (2)

String include() default"all";                   (3)

)

(1)

usage: 给定缓存的并发策略(NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)

(2)

region (可选的):缓存范围(默认为类的全限定类名或是集合的全限定角色名)

(3)

include (可选的):值为all时包括了所有的属性(proterty), 为non-lazy时仅含非延迟属性(默认值为all)

5、   应用范围

没有变化,近似于静态的数据。

6、   二级缓存的管理:

1、   清除指定实体类的所有数据

SessionFactory.evict(Student.class);

2、   清除指定实体类的指定对象

SessionFactory.evict(Student.class, 1);//第二个参数是指定对象的ID,就可以清除指定ID的对象

使用SessionFactory清除二级缓存

Sessionsession = null;

try {

session = HibernateUtils.getSession();

session.beginTransaction();

Student student = (Student)session.load(Student.class, 1);

System.out.println("student.name=" +student.getName());

session.getTransaction().commit();

}catch(Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

}finally {

HibernateUtils.closeSession(session);

}

//管理二级缓存

SessionFactory factory = HibernateUtils.getSessionFactory();

//factory.evict(Student.class);

factory.evict(Student.class, 1);

try {

session = HibernateUtils.getSession();

session.beginTransaction();

//会发出查询sql,因为二级缓存中的数据被清除了

Student student = (Student)session.load(Student.class, 1);

System.out.println("student.name=" +student.getName());

session.getTransaction().commit();

}catch(Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

}finally {

HibernateUtils.closeSession(session);

}

7、   二级缓存的交互

Sessionsession = null;

try {

session = HibernateUtils.getSession();

session.beginTransaction();

//仅向二级缓存读数据,而不向二级缓存写数据

session.setCacheMode(CacheMode.GET);

Student student =(Student)session.load(Student.class, 1);

System.out.println("student.name=" +student.getName());

session.getTransaction().commit();

}catch(Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

}finally {

HibernateUtils.closeSession(session);

}

try {

session = HibernateUtils.getSession();

session.beginTransaction();

//发出sql语句,因为session设置了CacheMode为GET,所以二级缓存中没有数据

Student student =(Student)session.load(Student.class, 1);

System.out.println("student.name=" +student.getName());

session.getTransaction().commit();

}catch(Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

}finally {

HibernateUtils.closeSession(session);

}

try {

session = HibernateUtils.getSession();

session.beginTransaction();

//只向二级缓存写数据,而不从二级缓存读数据

session.setCacheMode(CacheMode.PUT);

//会发出查询sql,因为session将CacheMode设置成了PUT

Student student =(Student)session.load(Student.class, 1);

System.out.println("student.name=" +student.getName());

session.getTransaction().commit();

}catch(Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

}finally {

HibernateUtils.closeSession(session);

}

CacheMode参数用于控制具体的Session如何与二级缓存进行交互。

·                                CacheMode.NORMAL - 从二级缓存中读、写数据。

·                                CacheMode.GET - 从二级缓存中读取数据,仅在数据更新时对二级缓存写数据。

·                                CacheMode.PUT - 仅向二级缓存写数据,但不从二级缓存中读数据。

·                                CacheMode.REFRESH - 仅向二级缓存写数据,但不从二级缓存中读数据。通过hibernate.cache.use_minimal_puts的设置,强制二级缓存从数据库中读取数据,刷新缓存内容。

如若需要查看二级缓存或查询缓存区域的内容,你可以使用统计(Statistics API。

Map cacheEntries = sessionFactory.getStatistics()
        .getSecondLevelCacheStatistics(regionName)
        .getEntries();

此时,你必须手工打开统计选项。可选的,你可以让Hibernate更人工可读的方式维护缓存内容。

hibernate.generate_statistics true
hibernate.cache.use_structured_entries true

8、   总结

load默认使用二级缓存,iterate默认使用二级缓存

list默认向二级缓存中加数据,但是查询时候不使用

三、 查询缓存

查询缓存,是用于缓存普通属性查询的,当查询实体时缓存实体ID。
默认情况下关闭,需要打开。查询缓存,对list/iterator这样的操作会起作用。
可以使用<property name=”hibernate.cache.use_query_cache”>true</property>来打开查询缓存,默认为关闭。
所谓查询缓存:即让hibernate缓存list、iterator、createQuery等方法的查询结果集。如果没有打开查询缓存,hibernate将只缓存load方法获得的单个持久化对象。
在打开了查询缓存之后,需要注意,调用query.list()操作之前,必须显式调用query.setCachable(true)来标识某个查询使用缓存。
查询缓存的生命周期:当前关联的表发生修改,那么查询缓存生命周期结束
注意查询缓存依赖于二级缓存,因为使用查询缓存需要打开二级缓存

查询缓存的配置和使用:

* 在hibernate.cfg.xml文件中启用查询缓存,如:

<propertyname="hibernate.cache.use_query_cache">true</property>

* 在程序中必须手动启用查询缓存,如:

         query.setCacheable(true);
 
例如:

session= HibernateUtils.getSession();

session.beginTransaction();

Query query = session.createQuery("selects.name from Student s");

//启用查询查询缓存

query.setCacheable(true);

List names = query.list();

for (Iterator iter=names.iterator();iter.hasNext();) {

String name =(String)iter.next();

System.out.println(name);

}

System.out.println("-------------------------------------");

query = session.createQuery("selects.name from Student s");

//启用查询查询缓存

query.setCacheable(true);

//没有发出查询sql,因为启用了查询缓存

names = query.list();

for (Iteratoriter=names.iterator();iter.hasNext(); ) {

String name =(String)iter.next();

System.out.println(name);

}

         session.getTransaction().commit();
 

Session session = sf.openSession();

session.beginTransaction();

List<Category>categories = (List<Category>)session.createQuery("from Category")

.setCacheable(true).list();

session.getTransaction().commit();

session.close();

Session session2 = sf.openSession();

session2.beginTransaction();

List<Category>categories2 = (List<Category>)session2.createQuery("from Category")

.setCacheable(true).list();

session2.getTransaction().commit();

         session2.close();
 
注:查询缓存的生命周期与session无关。
查询缓存只对query.list()起作用,query.iterate不起作用,也就是query.iterate不使用

四、 缓存算法

1、  LRU、LFU、FIFO

HIbernate学习笔记(八) hibernate缓存机制的更多相关文章

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

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

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

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

  3. HIbernate学习笔记3 之 缓存和 对象的三种状态

    一.hibernate一级缓存 *  hibernate创建每个Session对象时,都会给该Session分配一块独立的缓冲区,用于存放Session查询出来的对象,这个分配给session的缓存区 ...

  4. Hibernate学习笔记(八) — 懒载入与抓取策略

    懒载入(Load On Demand)是一种独特而又强大的数据获取方法,它可以在用户滚动页面的时候自己主动获取很多其它的数据,而新得到的数据不会影响原有数据的显示,同一时候最大程度上降低server端 ...

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

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

  6. Hibernate学习笔记(一)

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

  7. Hibernate学习笔记(二)

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

  8. Hibernate 学习笔记一

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

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

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

  10. go微服务框架kratos学习笔记八 (kratos的依赖注入)

    目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...

随机推荐

  1. HDU 2159 FATE (DP 二维费用背包)

    题目链接 题意 : 中文题不详述. 思路 : 二维背包,dp[i][h]表示当前忍耐值为i的情况下,杀了h个怪得到的最大经验值,状态转移方程: dp[i][h] = max(dp[i][h],dp[i ...

  2. hdu 2897 邂逅明下 博弈论

    这个分区间: 1<=n%(p+q)<=p 必败 其他必胜! 代码如下: #include<iostream> #include<stdio.h> #include& ...

  3. 一周一话题之四(JavaScript、Dom、jQuery全面复习总结<Dom篇>)

    -->目录导航 一. 初探Dom 1. Dom介绍 二. Dom基础 1. window顶级对象 2. body.document对象事件 3. 通用的HTML元素的事件 4. 冒泡事件 5. ...

  4. 在自己的网站上实现QQ授权登录

    最近在实现QQ授权登录,现将我的实现过程以及我的理解整理如下.以下所述如有不对之处,请指正. 官方提供的SDK有:JS,PHP,Java.我的网站使用Scala+Play搭建的,所以只能用JS SDk ...

  5. 一张图让你看懂锻压、CNC、压铸、冲压四类工艺!

    (锻压+CNC+阳极.CNC+阳极.压铸+阳极.冲压+阳极手机外壳比较) 上图为一张雷达图,该图比较直观形象地描述了4大手机外壳工艺在6个维度(加工成本.CNC用量.加工周期.成品率.可设计性.外观质 ...

  6. vs 下 opengl 配置问题

    项目 -->选择属性 C\C++-->preprocessor-->preprocessor definition 添加GLUT_BUILDING_LIB,中间用分号隔开. 然后点击 ...

  7. Python字符串编码问题

    编码问题:Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了. ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节.字母A用ASC ...

  8. [原]数据库中的partitioning和sharding

    1. 如何理解定义 在中文中,partitioning和sharding都有分区的意思.从大的方面来说,这两个词所执行的动作确实也和分区相关.partitioning在很多场合是vertical pa ...

  9. 在Vim里使用gtags-cscope

    用Vundle安装好gtags-cscope后,要在vimrc里添加如下设置: " cscopeset cscopetag                  " 使用 cscope ...

  10. How to download a website for offline usage

    wget -U Mozilla --recursive --no-clobber --page-requisites --html-extension --convert-links -- restr ...