Hibernate缓存机制

Hibernate缓存机制

缓存:缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。

hibernate缓存主要包括两个部分:Session缓存和SessionFactory缓存


-Hibernate Session缓存

“Session的缓存”也称为Hibernate一级缓存,它是内置的,不能被卸载(不能被卸载的意思就是这种缓存不具有可选性,必须有的功能,不可以取消session缓存)。

-Hibernate SessionFactory缓存

SessionFactory的缓存又可以分为两类:内置缓存和外置缓存。SessionFactory的内置缓存和Session的缓存在实现方式上比较相似,前者是SessionFactory对象的一些集合属性包含的数据,后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来,SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。


-缓存范围

缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。

  • 1 、事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的的对象形式。

  • 2 、进程范围:缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期,进程结束时,缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据,所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据,但是对象分解为松散的算法比对象序列化的算法要求更快。

  • 3 、集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式。对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,因为访问的速度不一定会比直接访问数据库数据的速度快多少。持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,还可以到进程范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存,通常它是必需的;进程范围或集群范围的缓存是持久化层的第二级缓存,通常是可选的。


由于一级缓存是事务级别的,所以属于事务范围。而二级缓存属于进程范围或者集群范围。我们也知道,当两个并发事务同时访问数据库相同的数据时,会带来并发问题,二级缓存就存在并发问题。

Hibernate为二级缓存提供了四种策略,每一种策略对应一种事务隔离级别。

  • 事务型:仅仅在托管环境中适用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。
  • 读写型:提供了Read Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题。
  • 非严格读写型:不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须为该数据配置一个很短的数据过期时间,从而尽量避免脏读。对于极少被修改,并且允许偶尔脏读的数据,可以采用这种并发访问策略。
  • 只读型:对于从来不会修改的数据,如参考数据,可以使用这种并发访问策略。

事务型并发访问策略是事务隔离级别最高,只读型的隔离级别最低。事务隔离级别越高,并发性能就越低。如果二级缓存中存放的数据会经常被事务修改,就不得不提高缓存的事务隔离级别,但是这又会降低并发性能。因此,只有符合以下条件的数据才适合存放到二级缓存中去:

  • 1 很少被修改的数据
  • 2 不是很重要的数据,允许出现偶尔并发的数据
  • 3 不会被并发访问的数据
  • 4 参考数据

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

  • 1 经常被修改的数据
  • 2 财务数据,绝对不允许出现并发
  • 3 与其他应用共享的数据。

-缓存管理

一级缓存管理

Session为应用程序提供了两个管理缓存方法:

-1 evict(obeject o):从缓存中清楚参数制定的持久化对象

-2 clear():清空缓存中所有持久化对象

Session的evict()方法能够从缓存中清除特定的持久化对象,它适用于以下情况:

  • 不希望Session继续按照该对象的状态变化俩同步更新数据库

  • 在批量更新或者批量删除的场合,当更新或删除一个对象后,及时释放该对象占用的内存。

实例:

当Session的evict方法把一个student对象从缓存中清除的时候,如果Session再次加载OID相同的student对象,他会重新创建一个student对象。


 tx=session.beginTransaction();  
 Student student1 = (Student)session.load(Student.class, 1);
 session.evict(student1); 


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

system.out.println(student1==student2); //打印 结 果 为 false

System.out.println(session.contains(student1)); //打印 结 果 为 false
System.out.println(session.contains(student2));//打印 结 果 为 true

student2.setAge(19);
student1.setAge(18);

tx=commit();

尽管student1和student2都是由同一个Session实例加载的,但是它们是不同的对象,即拥有不同的内存。Session的contains方法用来判断一个对象是否位于缓存中,它返回boolean类型的结果。对于以上程序,session.contains(student1)返回false,而session.contains(student2)返回true。当执行tx .commit()方法是,student1对象已经不再session缓存中,处于游离状态,而student2对象位于session缓存中,处于持久化状态,因此session按照student2的状态来同步更新数据库中的student表。

当通过session的evict方法清除缓存中的一个对象时,如果在映射文件中映射关联关系的cascade属性为all或者all-delete-orphan,会级联清除关联对象。

二级缓存管理

Hibernate二级缓存是进程或者集群范围内的缓存。二级缓存是可配置的插件,Hibernate允许以下类型的缓存插件:

  • ◆EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
  • ◆OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
  • ◆SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。
  • ◆JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。

各种缓存插件支持的并发访问策略

缓存插件 只读型 非严格读写型 读写型 事务型
EhCache 支持 支持 支持
OSCache 支持 支持 支持
SwarmCache 支持 支持
JBossCache 支持 支持

hibernate为以上缓存插件分别提供了内置的Cacheprovider实现:

缓存插件 提供器(CacheProvider)
EhCache org.hibernate.cache.EhCacheProvider
OSCache org.hibernate.cache.OSCacheProvider
SwarmCache org.hibernate.cache.SwarmCacheProvider
JBossCache org.hibernate.cache.TreeCacheProvider

在默认情况下,Hibernate使用EhCache进行JVM级别的缓存。用户可以通过设置Hibernate配置文件中的hibernate.cache.provider_class的属性,指定其他的缓存策略,该缓存策略必须实现org.hibernate.cache.CacheProvider接口。

配置二级缓存的主要步骤:

  • 选择需要使用二级缓存的持久化类,设置它的命名缓存的并发访问策略。

  • 选择合适的缓存插件,然后编辑该插件的配置文件。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。