[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二级缓存剩下的内容,比如你修改.删除数据时 ...
随机推荐
- MVC5 Entity Framework学习之实现继承
之前你已经学习了怎样处理并发异常,在本节中你将学习怎样实现继承. 在面向对象的编程中,你能够使用继承来重用代码.接下来你将改动Instructor和Student类,让它们派生自Person基类,该基 ...
- How to Use NSLog to Debug CGRect and CGPoint
转载: http://iosdevelopertips.com/debugging/how-to-use-nslog-to-debug-cgrect-and-cgpoint.html CGPoint ...
- HTTP请求中POST与GET的差别
一.原理差别 一般我们在浏览器输入一个网址訪问站点都是GET请求;再FORM表单中,能够通过设置Method指定提交方式为GET或者POST提交方式,默觉得GET提交方式. HTTP定义了与serve ...
- 09应用输入经理旋转场景--《猿学校课程Unity3d》
为什么极品飞车游戏等.,我们可以通过系统设置非常的方面根据自己喜欢的操作模式设置,有些人喜欢用箭头来控制不喜欢与使用"W,S,A,D"控制,这就解释程序猿不会死在程序写入内部控制, ...
- MySQL之终端(Terminal)管理MySQL
原文:MySQL之终端(Terminal)管理MySQL 前言:MySQL有很多的可视化管理工具,比如“mysql-workbench”和“sequel-pro-”. 现在我写MySQL的终端命令操作 ...
- 分布式中使用Redis实现Session共享(转)
上一篇介绍了如何使用nginx+iis部署一个简单的分布式系统,文章结尾留下了几个问题,其中一个是"如何解决多站点下Session共享".这篇文章将会介绍如何使用Redis,下一篇 ...
- rm-rf 恢复过程中滥用
多DBA一定rm -rf讨厌它,也许有一天自己将数据库,以消除一个中午,然后.那么就没有一个--这种情况下,--这个不幸真的发生,你真的无药可救?不必要,有解决方法.也许你遇到不幸时,有一天.你可以用 ...
- ABP项目中的使用AutoMapper
AutoMapper之ABP项目中的使用 最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMa ...
- WiX Toolset
原文:WiX Toolset 公司换软件打包平台,弄了一个月,Wix toolset的中文资料真的不多,逼着自己看了不少英文资料,终于弄懂了WiX打包的过程,做出了满足要求的安装包 一点基本概念:(F ...
- Arrays.asList的那点事
import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List ...