NHibernate教程(20)——二级缓存(上)
本节内容
- 引入
- 介绍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)——二级缓存(上)的更多相关文章
- NHibernate教程(21)——二级缓存(下)
本节内容 引入 使用NHibernate二级缓存 启用缓存查询 管理NHibernate二级缓存 结语 引入 这篇我还继续上一篇的话题聊聊NHibernate二级缓存剩下的内容,比如你修改.删除数据时 ...
- NHibernate系列文章九:NHibernate对象二级缓存上
摘要 NHibernate的二级缓存由SessionFactory管理,由所有Session共享. NHibernate缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...
- NHibernate教程(19) —— 一级缓存
本节内容 引入 NHibernate一级缓存介绍 NHibernate一级缓存管理 结语 引入 大家看看上一篇了吗?对象状态.这很容易延伸到NHibernate的缓存.在项目中我们灵活的使用NHibe ...
- NHibernate使用MemCache二级缓存
首先,当然是安装MemCache服务器端了. 然后配置过程,仅仅两个问题. 1.NHibernate要与NHibernate.Cache的版本要一致.否则,NHibernate.Caches.MemC ...
- [Nhibernate]二级缓存(二)
目录 写在前面 文档与系列文章 更新数据 二级缓存管理 总结 写在前面 本篇文章也算nhibernate入门系列的结尾了,在总结nhibernate系列的过程中,遇到了很多问题,学习的过程也是解决bu ...
- [Nhibernate]二级缓存
[Nhibernate]二级缓存 目录 写在前面 文档与系列文章 二级缓存 Nhibernate二级缓存提供程序 一个例子 总结 写在前面 上篇文章介绍了nhibernate中一级缓存的相关内容,一级 ...
- [Nhibernate]二级缓存(一)
目录 写在前面 文档与系列文章 二级缓存 Nhibernate二级缓存提供程序 一个例子 总结 写在前面 上篇文章介绍了nhibernate中一级缓存的相关内容,一级缓存过期时间和ISession对象 ...
- NHibernate系列文章十:NHibernate对象二级缓存下
摘要 上一节对NHibernate二级缓存做了简单介绍,NHibernate二级缓存是由SessionFactory管理的,所有Session共享.这一节介绍二级缓存其他两个方面:二级缓存查询和二级缓 ...
- 基于NHibernate二级缓存的MongoDB组件
设计一套基于NHibernate二级缓存的MongoDB组件(上) 摘要:NHibernate Contrib 支持很多第三方的二级缓存,如SysCache,MemCache,Prevalence ...
随机推荐
- cacti监控部署与配置
cacti是一套基于PHP,mysql,SNMP及RRDTool开发的网络流量测试图形分析工具 cacti是通过snmpget来获取数据,使用RRDtool绘画图形 ,而且完全可以不需要了解RRDto ...
- <Mastering KVM Virtualization>:第一章 了解Linux虚拟化
本章为读者提供了Linux虚拟化中流行技术的深刻见解,以及相较于其他同类技术的优势特点.本书共有14章,囊括了KVM虚拟化中的各个方面,从KVM的内部构造开始,并包括了诸如软件定义网络(SDN),性能 ...
- Nodejs package.json文件介绍
每个npm的安装包里面都会包含一个package.json,通常这个文件会在包的根目录下. 这个文件很类似于.net项目中的.csproj+AssemblyInfo.cs+App.config文件,主 ...
- 【Java学习笔记之八】java二维数组及其多维数组的内存应用拓展延伸
多维数组声明 数据类型[][] 数组名称; 数据类型[] 数组名称[]; 数据类型数组名称[][]; 以上三种语法在声明二维数组时的功能是等价的.同理,声明三维数组时需要三对中括号,中括号的位置可以在 ...
- vue2.0 新手教程
想想自己写vue的项目也写了一年了,从vue1.0到2.0,走过不少路,填过不少坑, 下面记录一下新手从0到1的过程,本文“应该”会持续更新 首先安装vue的运行环境node 1.下载Nodejs并安 ...
- HDU 6006 Engineer Assignment:状压dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6006 题意: 在Google中,有个n项目,m个专家.第i个项目涉及c[i]个领域,分别为a[i][0 ...
- 开源社交系统ThinkSNS+ V0.8.0 正式发布(一期功能版本)
智士软件旗下开源sns社交系统ThinkSNS即将进入10周年,推出并行两代系统ThinkSNSV4和ThinkSNS+,以专业易用的技术源码输出,驱动互联网社交软件建设及创业,使用ThinkSNS改 ...
- UNIX 技巧: UNIX 高手的另外 10 个习惯
让我们面对现实吧:坏习惯很难改变.但是您已经熟悉的习惯可能更难克服.有时,重新审视某些事情可能让您遇到“啊哈,我没想到它能做到这一点!”的时刻.在 Michael Stutz 的优秀文章“UNIX 高 ...
- python 在大文件里面删除某一行,比较有效率的方法
用 python 处理一个文本时,想要删除其中中某一行,常规的思路是先把文件读入内存,在内存中修改后再写入源文件. 但如果要处理一个很大的文本,比如GB级别的文本时,这种方法不仅需要占用很大内存,而且 ...
- MySQL中的数据类型及创建
MySQL创建: 1.创建数据库create database test2; 2.删除数据库drop database test2;3.创建表create table ceshi( ids in ...