[Nhibernate]二级缓存
[Nhibernate]二级缓存
目录
写在前面
上篇文章介绍了nhibernate中一级缓存的相关内容,一级缓存过期时间和ISession对象的生命周期相同,并且不同的Session不能共享缓存,一级缓存也可以成为ISession缓存。那么现在我们就学一下nhibernate中的二级缓存,即ISessionFactory级别缓存,可被所有的ISession所共享。二级缓存是可扩展的,在http://sourceforge.net/projects/nhcontrib/上提供了第三方的Nhibernate二级缓存提供程序。
文档与系列文章
[NHibernate]持久化类(Persistent Classes)
[NHibernate]集合类(Collections)映射
[NHibernate]缓存(NHibernate.Caches)
[NHibernate]NHibernate.Tool.hbm2net
[NHibernate]Nhibernate如何映射sqlserver中image字段
[NHibernate]条件查询Criteria Query
[Nhibernate]SchemaExport工具的使用(一)——通过映射文件修改数据表
[Nhibernate]SchemaExport工具的使用(二)——创建表及其约束、存储过程、视图
二级缓存
关于二级缓存的详细可以参考[NHibernate]缓存(NHibernate.Caches)。
NHibernate session有一个内部的(一级)缓存,存放着它的实体。这些缓存没有共享,因此session被销毁时它的缓存也被销毁了。NHibernate提供了二级缓存系统;它在SessionFactory级别工作。因此它被同一个SessionFactory产生的session共享。
在NHibernate中,当我们启用NHibernate二级缓存。
使用ISession进行数据操作时,NHibernate首先从内置缓存(一级缓存)中查找是否存在需要的数据,如果内置缓存不存在需要的数据,则查询二级缓存,如果二级缓存中存在所需数据,则直接使用缓存中数据,否则从数据库中查询数据并放入缓存中。
NHibernate本身提供了一个基于Hashtable的HashtableCache缓存,但是功能非常有限而且性能比较差,不适合在大型应用程序使用,我们可以使用第三方缓存提供程序作为NHibernate二级缓存实现。
使用缓存的缺点:
如果缓存策略设置不当,NHibernate不知道其它应用程序对数据库的修改及时更新缓存。因此,建议只对系统经常使用、数据量不大且不会被其它应用程序修改的只读数据(或很少被修改的数据)使用缓存。
Nhibernate二级缓存提供程序
NHibernate提供了NHibernate.Cache.ICacheProvider接口用来支持第三方缓存提供程序实现。开发缓存提供程序时,需要实现该接口作为NHibernate和缓存实现直接的适配器。NHibernate提供了常见的缓存提供程序的内置适配器,这些适配器都实现了NHibernate.Cache.ICacheProvider接口。
NHibernate.Cache.ICacheProvider定义如下:
NHibernate.Cache.ICacheProvider
除了NHibernate本身提供的一个基于Hashtable的HashtableCache缓存。
在NHibernate Contrib上提供了六种第三方NHibernate二级缓存提供程序,完全开源的。我们直接下载其程序集引用到我们的项目中就可以使用了。
- NHibernate.Caches.MemCache
- NHibernate.Caches.Prevalence
- NHibernate.Caches.SharedCache
- NHibernate.Caches.SysCache
- NHibernate.Caches.SysCache2
- NHibernate.Caches.Velocity
一个例子
如何使用?
在默认情况下,NHibernate不启动二级缓存。如果要使用二级缓存则需要在NHibernate配置文件中显式的启用二级缓存。NHibernate二级缓存可以分别为每一个具体的类和集合配置应用级或分布式缓存。
缓存并发策略
当两个独立的事务同时访问数据库时,可能产生丢失更新、不可重复读等并发问题。同样,当两个并发事务同时访问缓存时,也有可能产生各种并发问题。因此,在缓存级别也需要设置相应的并发访问策略。
NHibernate内置四种并发访问策略:
- read-only:只读缓存。适用于只读数据。可用于群集中。
- read-write:读写缓存。
- nonstrict-read-write:非严格读写缓存。不保证缓存与数据库的一致性。
- transactional:事务缓存。提供可重复读的事务隔离级别。
配置缓存
在NHibernate配置文件中通过cache.provider_class属性显式指定缓存实现,属性值为缓存适配器的具体类名。如果你使用上面的第三方缓存提供程序,还需要配置缓存提供程序本身,关于第三方缓存提供程序的配置可以参考文档[NHibernate]缓存(NHibernate.Caches)。首先是从Nhibernate本身自带的HashtableCache缓存入手,学习一下缓存如何配置。
在nhibernate配置文件中显示指定缓存提供者类
1 <property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider</property>
1 <!--显示启用二级缓存,用cache.use_second_level_cache属性显式启用二级缓存,参数为Bool值,这里启用设置为true-->
2 <property name="cache.use_second_level_cache">true</property>
如果使用第三方缓存提供程序,那么需要对第三方缓存提供程序本身进行配置,需要详细配置第三方缓存提供程序缓存属性:保存时间、过期时间、可以缓存对象数量。
为每一个持久化类和集合指定相应的缓存策略
方法一:在映射文件中通过<cache>元素配置类和集合的缓存策略,在Class元素或者集合元素中添加<cache>元素进行配置。注意:<cache>元素必须在<id>元素之前。
1 <cache usage="read-only|read-write|nonstrict-read-write" region="默认类或集合名称"/>
方法二:在NHibernate配置文件hibernate.cfg.xml中通过<class-cache>元素和<collection-cache>元素分别配置类和集合的缓存策略。
1 <class-cache class="类名称" region="默认类名称" include="all|non-lazy"
2 usage="read-only|read-write|nonstrict-read-write|transactional" />
<!--指定集合-->
<collection-cache collection ="集合名称" region="默认集合名称"
usage="read-only|read-write|nonstrict-read-write|transactional"/>
属性含义
- region:可选,默认值为类或集合的名称,用来指定二级缓存的区域名,对应于缓存实现的一个命名缓存区域。
- include:可选,默认值为all,当取non-lazy时设置延迟加载的持久化实例的属性不被缓存。
- usage:声明缓存同步策略,就是上面说明的四种缓存策略。
有两种方式定义缓存策略,到底选择那种好?
在nhibernate配置文件中你可以为每个类设置更方便,维护起来也方便,如果在每个持久化类中分别设置缓存策略,维护起来有点麻烦。
测试
在nhibernate中启用二级缓存,并指定缓存Customer类

1 <?xml version="1.0" encoding="utf-8" ?>
2 <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
3 <session-factory>
4 <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
5 <property name="connection.connection_string">
6 server=.;database=shop;uid=sa;pwd=sa
7 </property>
8 <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
9 <property name="show_sql">true</property>
10 <!--二级缓存配置-->
11 <!--cache.provider_class属性显式指定缓存实现,属性值为缓存适配器的具体类名-->
12 <property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider</property>
13 <!--显示启用二级缓存,用cache.use_second_level_cache属性显式启用二级缓存,参数为Bool值,这里启用设置为true-->
14 <property name="cache.use_second_level_cache">true</property>
15 <!--启用查询缓存-->
16 <property name ="cache.use_query_cache">true</property>
17 <mapping assembly="Wolfy.Shop.Domain"/>
18 <!--Customer类启用二级缓存-->
19 <class-cache class="Wolfy.Shop.Domain.Entities.Customer,Wolfy.Shop.Domain" usage="read-write"/>
20 </session-factory>
21 </hibernate-configuration>

Customer.hbm.xml映射文件
在不同的Session中查询实体

1 /// <summary>
2 /// 根据客户id查询
3 /// </summary>
4 /// <param name="customerID"></param>
5 /// <returns></returns>
6 public Customer GetCustomerById(Guid customerID)
7 {
8 ISession session = NHibernateHelper.GetSession();
9 return session.Get<Customer>(customerID);
10 }
11 /// <summary>
12 /// 根据客户id查询
13 /// </summary>
14 /// <param name="customerID"></param>
15 /// <returns></returns>
16 public Customer GetCustomerById2(Guid customerID)
17 {
18 //重置Session
19 ISession session = NHibernateHelper.ResetSession();
20 return session.Get<Customer>(customerID);
21 }

单元测试

1 [TestMethod]
2 public void GetCustomerById2Test()
3 {
4 Console.WriteLine("Session1 第一次加载");
5 Customer c1 = _customerData.GetCustomerById(new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));
6 Assert.IsNotNull(c1);
7 Console.WriteLine("Session2 第二次加载");
8 Customer c2 = _customerData.GetCustomerById2(new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));
9 Assert.IsNotNull(c2);
10 }

在第一次查询数据时,由于一级、二级缓存中都不存在需要的数据,这时NHibernate从数据库中查询数据。第二次读取同一数据,NHibernate首先从内置缓存(一级缓存)中查找是否存在所需要数据,由于不是在同一个ISession中,所以内置ISession缓存中不存在所需数据,NHibernate则查询二级缓存,这时由于第一次查询了这条数据,所以在二级缓存中存在所需数据,则直接使用缓存中数据。(该测试方法与一级缓存中的测试方法相同,为了方便对比,将上篇文章中的图贴在一起进行对比)
一级缓存测试结果
二级缓存测试结果
通过对比,可以发现在单元测试中第二次会话,断言c2不为null通过了测试,说明c2是从缓存中取的。也印证了ISessionFactory级别的二级缓存是可以共享缓存的。
总结
在学习nhibernate过程中难免遇到各种各样的错误,学习的过程也是解决各种异常的过程。
关于二级缓存中简单的查询缓存就介绍到这里,下篇文章将介绍二级缓存针对删除,修改的策略及缓存的管理的内容。
参考文章
[Nhibernate]二级缓存的更多相关文章
- [Nhibernate]二级缓存(一)
目录 写在前面 文档与系列文章 二级缓存 Nhibernate二级缓存提供程序 一个例子 总结 写在前面 上篇文章介绍了nhibernate中一级缓存的相关内容,一级缓存过期时间和ISession对象 ...
- [Nhibernate]二级缓存(二)
目录 写在前面 文档与系列文章 更新数据 二级缓存管理 总结 写在前面 本篇文章也算nhibernate入门系列的结尾了,在总结nhibernate系列的过程中,遇到了很多问题,学习的过程也是解决bu ...
- 01-08-05【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate二级缓存:第三方MemCache缓存
一.准备工作 [1]根据操作系统(位数)选择下载相应版本的MemCache, MemCache的下载和安装,参看: http://www.cnblogs.com/easy5weikai/p/37606 ...
- 基于NHibernate二级缓存的MongoDB组件
设计一套基于NHibernate二级缓存的MongoDB组件(上) 摘要:NHibernate Contrib 支持很多第三方的二级缓存,如SysCache,MemCache,Prevalence ...
- NHibernate二级缓存(第十一篇)
NHibernate二级缓存(第十一篇) 一.NHibernate二级缓存简介 NHibernate由ISessionFactory创建,可以被所有的ISession共享. 注意NHibernate查 ...
- NHibernate系列文章九:NHibernate对象二级缓存上
摘要 NHibernate的二级缓存由SessionFactory管理,由所有Session共享. NHibernate缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...
- NHibernate系列文章十:NHibernate对象二级缓存下
摘要 上一节对NHibernate二级缓存做了简单介绍,NHibernate二级缓存是由SessionFactory管理的,所有Session共享.这一节介绍二级缓存其他两个方面:二级缓存查询和二级缓 ...
- 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之缓存管理
http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 管理NHibernate二级缓存 NHibernate二级缓存由ISessionF ...
- NHibernate教程(21)——二级缓存(下)
本节内容 引入 使用NHibernate二级缓存 启用缓存查询 管理NHibernate二级缓存 结语 引入 这篇我还继续上一篇的话题聊聊NHibernate二级缓存剩下的内容,比如你修改.删除数据时 ...
随机推荐
- AndroidSlidingUpPanel
使用控制和简单的分析方法
滑 - 向上的时间可以飞起来控件的显示区域.分类似至play music有效. 该控件在主界面中有一个例如以下图红色箭头所指的底部触发区域: 该区域点击的时候被隐藏在下方的内容将网上漂移到顶部,直到被 ...
- lodoop打印控制具体解释
注意:这就需要引进的打印控制(我上传Demo同时): install_lodop32.exe install_lodop64.exe LodopFuncs.js jquery-1.10.0.min.j ...
- 看德日进,凯文·凯利与Kurzweil老师?
生命从哪里来.要到那里去.生命存在的意义是什么.这些差点儿是人类可以探究的最深层次问题.基督教给出的答案是毁灭和审判.佛学给出的答案是无常,科学的达尔文进化论给出了生命的起点和进化的过程,对于未来.达 ...
- 一张地图告诉你,只JavaScript不够!
这将是JavaScript语法,你真的会一JavaScript嘛.看看这个图片!超好用JavaScript一本书的摘录游.熊儿.快去学习! 版权声明:本文博客原创文章.博客,未经同意,不得转载.
- 如何使用iOS 8 指纹识别,代码、示例
像想象,iOS 8指纹是非常容易使用的.只是需要能够获得一个接口,弹出屏幕模式框,随着app store在相同的. 直接上的条形码.以下代码是从复制Apple官方文件. 加入LocalAuthenti ...
- Angular报错记录
一 找不到Controller 出现这种错误,一般都是没有找到需要的Controller,需要仔细检查是否所需的Controller已经正确引入
- Oracle语句优化1
Oracle语句优化1 优化就是选择最有效的方法来执行SQL语句.Oracle优化器选择它认为最有效的 方法来执行SQL语句. 1. IS NULL和IS NOT ...
- 打造简易可扩展的jQuery/CSS3 Tab菜单
原文:打造简易可扩展的jQuery/CSS3 Tab菜单 今天我们利用jQuery和CSS3来打造一款简易而且扩展性强的Tab菜单,这款Tab菜单在切换时也有滑块的效果,先来看看效果图: 由与Tab菜 ...
- RQNOJ PID4 / 数列(位运算)
题目描述 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是: 1,3,4,9,10,12,13,… (该序列实际上就是 ...
- Java设计模式之装饰者模式
要实现装饰者模式,注意一下几点内容: 1.装饰者类要实现真实类同样的接口 2.装饰者类内有一个真实对象的引用(可以通过装饰者类的构造器传入) 3.装饰类对象在主类中接受请求,将请求发送给真实的对象(相 ...