[Nhibernate]一级缓存
- 作者: 五速梦信息网
- 时间: 2026年04月04日 13:58
目录
写在前面
上篇文章介绍了nhibernate中对象的三种状态,通过对象的三种状态,很容易想到缓存。
什麽是缓存?
有时候,某些数据是会经常需要访问的,像硬盘内部的缓存(暂存器的一种)会将读取比较频繁的一些数据存储在缓存中,再次读取时就可以直接从缓存中直接传输。说白了,缓存是用空间换取时间的一种技术。
文档与系列文章
一级缓存
关于缓存的详细内容可以查看nhibernate文档
NHibernate session有一个内部的(一级)缓存,存放着它的实体。这些缓存没有共享,因此session被销毁时它的缓存也被销毁了。
NHibernate提供了二级缓存系统;它在SessionFactory级别工作。因此它被同一个SessionFactory产生的session共享。
使用每个请求(request)一个session模式,很多Session可以并发的访问同一个实体,而不用每次都访问数据库,因此性能获得了提升。
可见一级缓存的过期时间是和session的生命周期相同的。
ISession实例创建后即可使用ISession缓存。此后,ISession实例操作数据时,首先查询内置缓存,如果ISession缓存中存在相应数据,则直接使用缓存数据。如果不存在,则查询数据库并把其结果存在缓存中。
为了方便测试,这里改用单元测试的方法进行(也顺便学习一下单元测试,说实话之前很少用这东西,自从使用之后,发现真是太方便了)。
一个例子
1、根据客户id查询符合条件的客户对象。
单元测试该方法
测试结果
当第一次加载数据时,缓存中还没有该数据,则从数据库中查询并将查询的结果放入缓存。第二次查询同一个持久化实例时,缓存中已经存在该持久化实例,应用程序将直接从缓存中获取数据,而不必再次从数据库中读取数据,提高了查询效率。
2、分别从两个会话中查询Customer
构建测试用例,因为获得ISession实例采用的单例模式,如果不进行重置那么Session是同一个对象,所以这里需要在第一次查询后重置ISession,NhibernateHelper代码如下:
修改GetCustomerById方法
单元测试
运行测试,结果
由上测试可以看出,在两个会话中获取同一持久化实例时,两个会话的缓存是独立的,一个会话的数据操作不会影响到另外一个会话。
从结果我们可以说明虽然这两个会话读取的是同一个实例,但需要至少两次数据库操作(关联的数据表除外),从而说明了Session缓存不是共享的,一个Session的缓存内容只有在本Session实例范围内可用。
3、ISession.Get()和ISession.Load()比较
分别使用Get和Load方法查询某个客户信息。
单元测试
运行单元测试,查看结果
使用ISession.Get()方法立即把对象实例保存到缓存中,使用ISession.Load()方法当你需要使用的时候再访问数据库把这个实例保存在缓存中(有点懒加载的意思,关于Lazy加载可参考前面的文章,Load方法默认是使用Lazy方式加载的)。
一级缓存管理
ISession接口为我们提供了一些常用方法来显式管理一级缓存:
ISession.Evict(object):从缓存中删除指定实例。
ISession.Clear():清空缓存。
ISession.Contains(object):检查缓存中是否包含指定实例。
在CustomerData中添加方法
单元测试方法
测试结果
该测试,首先加载两个customer实例,此时已将它们都存入一级缓存,首先使用RemoveCustomerFromCache方法,从缓存中将customer1对象移除,然后使用ClearCache方法清空缓存。
总结
本篇文章就到这里,一级缓存是和ISession关联的,多个Session的缓存是不能共享的。本篇文章使用了单元测试的方式进行测试,也是首次使用单元测试,也稍微研究了一下,关于单元测试的东西,算是附加学习的吧。
参考文章
- 上一篇: [No0000139]轻量级文本编辑器,Notepad最佳替代品:Notepad++
- 下一篇: [Ngbatis源码学习][SpringBoot] ApplicationContextInitializer接口类的使用和原理解读
相关文章
-
[No0000139]轻量级文本编辑器,Notepad最佳替代品:Notepad++
[No0000139]轻量级文本编辑器,Notepad最佳替代品:Notepad++
- 互联网
- 2026年04月04日
-
[NodeJS] 优缺点及适用场景讨论
[NodeJS] 优缺点及适用场景讨论
- 互联网
- 2026年04月04日
-
[OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget (第一部分)
[OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget (第一部分)
- 互联网
- 2026年04月04日
-
[Ngbatis源码学习][SpringBoot] ApplicationContextInitializer接口类的使用和原理解读
[Ngbatis源码学习][SpringBoot] ApplicationContextInitializer接口类的使用和原理解读
- 互联网
- 2026年04月04日
-
[mysql]设置Ubuntu上的MySQL可以远程访问
[mysql]设置Ubuntu上的MySQL可以远程访问
- 互联网
- 2026年04月04日
-
[MFC]获取一些用户文件夹
[MFC]获取一些用户文件夹
- 互联网
- 2026年04月04日






