本节内容

  • 引入
  • 介绍NHibernate二级缓存
  • NHibernate二级缓存提供程序
  • 实现NHibernate二级缓存
  • 结语

引入

上一篇我介绍了NHibernate内置的一级缓存即ISession缓存。这篇我们来了解下NHibernate二级缓存即ISessionFactory级别缓存。二级缓存是可扩展的,在NHibernate  Contrib上提供了第三方NHibernate二级缓存提供程序。

介绍NHibernate二级缓存

NHibernate二级缓存由ISessionFactory创建,可以被所有的ISession共享。

在NHibernate中,当我们启用NHibernate二级缓存。使用ISession进行数据操作时,NHibernate首先从内置缓存(一级缓存)中查找是否存在需要的数据,如果内置缓存不存在需要的数据,则查询二级缓存,如果二级缓存中存在所需数据,则直接使用缓存中数据,否则从数据库中查询数据并放入缓存中。

NHibernate本身提供了一个基于Hashtable的HashtableCache缓存,但是功能非常有限而且性能比较差,不适合在大型应用程序使用,我们可以使用第三方缓存提供程序作为NHibernate二级缓存实现。

但是,使用缓存的缺点就是如果缓存策略设置不当,NHibernate不知道其它应用程序对数据库的修改及时更新缓存。因此,建议只对系统经常使用、数据量不大且不会被其它应用程序修改的只读数据(或很少被修改的数据)使用缓存。

NHibernate二级缓存提供程序

NHibernate提供了NHibernate.Cache.ICacheProvider接口用来支持第三方缓存提供程序实现。开发缓存提供程序时,需要实现该接口作为NHibernate和缓存实现直接的适配器。NHibernate提供了常见的缓存提供程序的内置适配器,这些适配器都实现了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配置文件中显式的启用二级缓存。NHibernate二级缓存可以分别为每一个具体的类和集合配置应用级或分布式缓存。

缓存并发策略

提示一下,在NHibernate官方文档中有介绍,详情请参考NHibernate官方文档。当两个独立的事务同时访问数据库时,可能产生丢失更新、不可重复读等并发问题。同样,当两个并发事务同时访问缓存时,也有可能产生各种并发问题。因此,在缓存级别也需要设置相应的并发访问策略。

NHibernate内置四种并发访问策略:

  • read-only:只读缓存。适用于只读数据。可用于群集中。
  • read-write:读写缓存。
  • nonstrict-read-write:非严格读写缓存。不保证缓存与数据库的一致性。
  • transactional:事务缓存。提供可重复读的事务隔离级别。

我们动手实现二级缓存吧~~~

Step1:配置第三方缓存提供程序

我们在NHibernate配置文件中通过cache.provider_class属性显式指定缓存实现,属性值为缓存适配器的具体类名。如果你使用上面的第三方缓存提供程序,还需要配置缓存提供程序本身。这里我设置NHibernate本身提供了一个基于Hashtable的HashtableCache缓存。

<property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider</property>

Step2:显式启用二级缓存

在NHibernate配置文件中使用cache.use_second_level_cache属性显式启用二级缓存,参数为Bool值,这里启用设置为true。

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

Step3:配置第三方缓存提供程序本身

如果你使用第三方缓存提供程序,那么需要对第三方缓存提供程序本身进行配置,需要详细配置第三方缓存提供程序缓存属性:保存时间、过期时间、可以缓存对象数量。这里我就使用NHibernate本身提供的HashtableCache缓存,所以这一步就省略了。

Step4:为每一个持久化类和集合指定相应的缓存策略

方法一:在映射文件中通过<cache>元素配置类和集合的缓存策略,在Class元素或者集合元素中添加<cache>元素进行配置。注意:<cache>元素必须在<id>元素之前。

<cache usage="read-only|read-write|nonstrict-read-write" region="默认类或集合名称"/>

方法二:在NHibernate配置文件hibernate.cfg.xml中通过<class-cache>元素和<collection-cache>元素分别配置类和集合的缓存策略。

我还是建议大家使用NHibernate配置文件定义缓存策略,这样可以避免在各个映射文件配置缓存定义而增大维护难度。

指定类:

<class-cache class="类名称" region="默认类名称" include="all|non-lazy"
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:声明缓存同步策略,就是上面说明的四种缓存策略。

配置文件和映射文件定义不一样,不知道是不是BUG。

Step5:开始测试

在测试之前,我们先看看上面的步骤我们完成了哪些内容。我贴出具体代码:

代码片段1:NHibernate配置文件:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="NHibernateSample.DAL.Test">
<!--
配置二级缓存实例文件
作者:李永京(YJingLee's Blog)
出处:http://lyj.cnblogs.com
-->
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Data Source=.\SQLEXPRESS;Initial Catalog=NHibernateSample;
Integrated Security=True;Pooling=False</property>
<property name="adonet.batch_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="use_outer_join">true</property>
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
<!--1.配置二级缓存提供程序-->
<property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider</property>
<!--2.显式启用二级缓存-->
<property name ="cache.use_second_level_cache">true</property>
<!--4.启动查询缓存(注:下一篇内容:http://lyj.cnblogs.com)-->
<property name="cache.use_query_cache">true</property>
<mapping assembly="DomainModel"/>
<!--3.配置映射的二级缓存-->
<class-cache class="DomainModel.Entities.Customer,DomainModel" usage="read-write"/>
</session-factory>
</hibernate-configuration>

代码片段2:Customer.hbm.xml映射文件:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DomainModel" namespace="DomainModel">
<!--
配置二级缓存映射文件
作者:李永京(YJingLee's Blog)
出处:http://lyj.cnblogs.com
-->
<class name ="DomainModel.Entities.Customer,DomainModel"
table="Customer">
<cache usage="read-write"/>
<id name="CustomerId" type="Int32" unsaved-value="0">
<generator class ="native"></generator>
</id>
<version name="Version" type="integer" unsaved-value="0"/>
<component name="Name" class="DomainModel.Entities.Name,DomainModel">
<property name="Firstname"/>
<property name ="Lastname"/>
</component>
<set name="Orders" table="`Order`" generic="true" inverse="true">
<cache usage="read-only"/>
<key column="Customer" foreign-key="FK_CustomerOrders"/>
<one-to-many class="DomainModel.Entities.Order,DomainModel"/>
</set>
</class>
</hibernate-mapping>

Step6:测试代码

在不同Session中获取实体:

[Test]
public void SessionFactoryCacheTest()
{
using (_session)
{
Console.WriteLine("--Session 1--读取持久化实例--");
Customer customer1 = _session.Get<Customer>(1);
Assert.IsNotNull(customer1);
}
ResetSession();
using (_session)
{
Console.WriteLine("--Session 2--读取持久化实例--");
Customer customer2 = _session.Get<Customer>(1);
Assert.IsNotNull(customer2);
}
}

分析一下:在第一次查询数据时,由于一级、二级缓存中都不存在需要的数据,这时NHibernate从数据库中查询数据。第二次读取同一数据,NHibernate首先从内置缓存(一级缓存)中查找是否存在所需要数据,由于不是在同一个ISession中,所以内置ISession缓存中不存在所需数据,NHibernate则查询二级缓存,这时由于第一次查询了这条数据,所以在二级缓存中存在所需数据,则直接使用缓存中数据。看看输出结果吧:

结语

好了,这篇就到这里吧!我们初步认识了NHibernate二级缓存,并用一个查询例子说明了一切,但是关于二级缓存还有很多内容,比如你修改、删除数据时,二级缓存是什么策略呢?我们如果使用查询缓存呢?如何管理NHibernate二级缓存呢?这就在下一篇揭晓吧

NHibernate教程(20)——二级缓存(上)的更多相关文章

  1. NHibernate教程(21)——二级缓存(下)

    本节内容 引入 使用NHibernate二级缓存 启用缓存查询 管理NHibernate二级缓存 结语 引入 这篇我还继续上一篇的话题聊聊NHibernate二级缓存剩下的内容,比如你修改.删除数据时 ...

  2. NHibernate系列文章九:NHibernate对象二级缓存上

    摘要 NHibernate的二级缓存由SessionFactory管理,由所有Session共享. NHibernate缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...

  3. NHibernate教程(19) —— 一级缓存

    本节内容 引入 NHibernate一级缓存介绍 NHibernate一级缓存管理 结语 引入 大家看看上一篇了吗?对象状态.这很容易延伸到NHibernate的缓存.在项目中我们灵活的使用NHibe ...

  4. NHibernate使用MemCache二级缓存

    首先,当然是安装MemCache服务器端了. 然后配置过程,仅仅两个问题. 1.NHibernate要与NHibernate.Cache的版本要一致.否则,NHibernate.Caches.MemC ...

  5. [Nhibernate]二级缓存(二)

    目录 写在前面 文档与系列文章 更新数据 二级缓存管理 总结 写在前面 本篇文章也算nhibernate入门系列的结尾了,在总结nhibernate系列的过程中,遇到了很多问题,学习的过程也是解决bu ...

  6. [Nhibernate]二级缓存

    [Nhibernate]二级缓存 目录 写在前面 文档与系列文章 二级缓存 Nhibernate二级缓存提供程序 一个例子 总结 写在前面 上篇文章介绍了nhibernate中一级缓存的相关内容,一级 ...

  7. [Nhibernate]二级缓存(一)

    目录 写在前面 文档与系列文章 二级缓存 Nhibernate二级缓存提供程序 一个例子 总结 写在前面 上篇文章介绍了nhibernate中一级缓存的相关内容,一级缓存过期时间和ISession对象 ...

  8. NHibernate系列文章十:NHibernate对象二级缓存下

    摘要 上一节对NHibernate二级缓存做了简单介绍,NHibernate二级缓存是由SessionFactory管理的,所有Session共享.这一节介绍二级缓存其他两个方面:二级缓存查询和二级缓 ...

  9. 基于NHibernate二级缓存的MongoDB组件

    设计一套基于NHibernate二级缓存的MongoDB组件(上)   摘要:NHibernate Contrib 支持很多第三方的二级缓存,如SysCache,MemCache,Prevalence ...

随机推荐

  1. [基础]PeopleSoft中的作业和调度作业集合定义

    PeopleSoft进程调度器可以使一个或多个进程作为一个组.这个组在PeopleSoft中被称为作业(Job). PeopleSoft进程被定义为单个任务,程序或例程,例如cobol程序或AE程序或 ...

  2. Open-Falcon第一步环境准备(小米开源互联网企业级监控系统)

    1.环境安装 本文采取rpm安装方式,大家也可以用源码包安装. wget http://download.fedoraproject.org/pub/epel/6/i386/epel-release- ...

  3. Sangmado 公共基础类库

    Sangmado 涵盖了支撑 .NET/C# 项目开发的最基础的公共类库,为团队在不断的系统开发和演进过程中发现和积累的最公共的代码可复用单元. Sangmado 公共类库设计原则: 独立性:不与任何 ...

  4. 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...

  5. angular学习(六)-- Filter

    2.6 过滤器:Filter 内置过滤器 currency number date json uppercase lowercase orderBy limitTo filter 自定义过滤器

  6. vue.js之组件(上篇)

    本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星! https://github.com/zwl-jasmine95/Vue_test 以下所有知 ...

  7. redis(1)

    什么是nosql 非关系型数据库 为什么要用nosql web2.0大规模动态网站的兴起 high performance ,高并发读写,动态页面展示与交互,比如微博点赞评论等操作,实时统计在线人数排 ...

  8. 常见C++面试题(三)

    strcpy和memcpy有什么区别?strcpy是如何设计的,memcpy呢?   strcpy提供了字符串的复制.即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束 ...

  9. c和fortran混编(基于GNU/Linux,转自 linzch)

    网 上说要分c为主程序和fortran为主程序两种情况讨论,其实我觉得不用,只要你了解生成可执行文件的机制.这个机制就是:不论是单一语言模块之间的 链接还是不同语言之间的混合链接,本质目的都是要链接器 ...

  10. 简单选择排序 Selection Sort 和树形选择排序 Tree Selection Sort

    选择排序 Selection Sort 选择排序的基本思想是:每一趟在剩余未排序的若干记录中选取关键字最小的(也可以是最大的,本文中均考虑排升序)记录作为有序序列中下一个记录. 如第i趟选择排序就是在 ...