[Nhibernate]一级缓存
发布日期:2021-08-29 19:53:23 浏览次数:2 分类:技术文章

本文共 9297 字,大约阅读时间需要 30 分钟。

目录

写在前面

上篇文章介绍了nhibernate中对象的三种状态,通过对象的三种状态,很容易想到缓存。

什麽是缓存?

有时候,某些数据是会经常需要访问的,像硬盘内部的缓存(暂存器的一种)会将读取比较频繁的一些数据存储在缓存中,再次读取时就可以直接从缓存中直接传输。说白了,缓存是用空间换取时间的一种技术。

文档与系列文章

 

 

 

一级缓存

 关于缓存的详细内容可以查看nhibernate文档

NHibernate session有一个内部的(一级)缓存,存放着它的实体。这些缓存没有共享,因此session被销毁时它的缓存也被销毁了。

NHibernate提供了二级缓存系统;它在SessionFactory级别工作。因此它被同一个SessionFactory产生的session共享。

使用每个请求(request)一个session模式,很多Session可以并发的访问同一个实体,而不用每次都访问数据库,因此性能获得了提升。

可见一级缓存的过期时间是和session的生命周期相同的。

ISession实例创建后即可使用ISession缓存。此后,ISession实例操作数据时,首先查询内置缓存,如果ISession缓存中存在相应数据,则直接使用缓存数据。如果不存在,则查询数据库并把其结果存在缓存中。

为了方便测试,这里改用单元测试的方法进行(也顺便学习一下单元测试,说实话之前很少用这东西,自从使用之后,发现真是太方便了)。

一个例子

1、根据客户id查询符合条件的客户对象。

1         ///  2         /// 根据客户id查询 3         ///  4         ///  5         /// 
6 public Customer GetCustomerById(Guid customerID) 7 { 8 ISession session = NHibernateHelper.GetSession(); 9 return session.Get
(customerID);10 }

单元测试该方法

1 namespace Wolfy.DataUnitTest 2 { 3     [TestClass] 4     public class CustomerDataTest 5     { 6         CustomerData _customerData = null; 7         public CustomerDataTest() 8         { 9             _customerData = new CustomerData();10         }11         [TestMethod]12         public void GetCustomerByIdTest()13         {14             Console.WriteLine("第一次加载");15             Customer c1 = _customerData.GetCustomerById(new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));16             Console.WriteLine("第二次加载");17             Customer c2 = _customerData.GetCustomerById(new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));18             Assert.AreEqual(c1, c2);19         }20     }21 }

测试结果

当第一次加载数据时,缓存中还没有该数据,则从数据库中查询并将查询的结果放入缓存。第二次查询同一个持久化实例时,缓存中已经存在该持久化实例,应用程序将直接从缓存中获取数据,而不必再次从数据库中读取数据,提高了查询效率。

2、分别从两个会话中查询Customer

构建测试用例,因为获得ISession实例采用的单例模式,如果不进行重置那么Session是同一个对象,所以这里需要在第一次查询后重置ISession,NhibernateHelper代码如下:

1 namespace Wolfy.Shop.Data 2 { 3     ///  4     /// 描述:nhibernate辅助类 5     /// 创建人:wolfy 6     /// 创建时间:2014-10-16 7     ///  8     public class NHibernateHelper 9     {10         private static ISessionFactory _sessionFactory;11         private static ISession _session;12         private static object _objLock = new object();13         private NHibernateHelper()14         {15 16         }17         /// 18         /// 创建ISessionFactory19         /// 20         /// 
21 public static ISessionFactory GetSessionFactory()22 {23 if (_sessionFactory == null)24 {25 lock (_objLock)26 {27 if (_sessionFactory == null)28 {29 //配置ISessionFactory30 _sessionFactory = (new Configuration()).Configure().BuildSessionFactory();31 }32 }33 }34 return _sessionFactory;35 36 }37 /// 38 /// 重置Session39 /// 40 ///
41 public static ISession ResetSession()42 {43 if (_session.IsOpen)44 _session.Close();45 _session = _sessionFactory.OpenSession(); ;46 return _session;47 }48 /// 49 /// 打开ISession50 /// 51 ///
52 public static ISession GetSession()53 {54 _sessionFactory = GetSessionFactory();55 if (_session == null)56 {57 lock (_objLock)58 {59 if (_session == null)60 {61 _session = _sessionFactory.OpenSession();62 }63 }64 }65 return _session;66 }67 }68 69 }

修改GetCustomerById方法

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

单元测试

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         }

运行测试,结果

由上测试可以看出,在两个会话中获取同一持久化实例时,两个会话的缓存是独立的,一个会话的数据操作不会影响到另外一个会话。

从结果我们可以说明虽然这两个会话读取的是同一个实例,但需要至少两次数据库操作(关联的数据表除外),从而说明了Session缓存不是共享的,一个Session的缓存内容只有在本Session实例范围内可用。

3、ISession.Get()和ISession.Load()比较

分别使用Get和Load方法查询某个客户信息。

1         ///  2         /// 根据客户id查询 3         ///  4         ///  5         /// 
6 public Customer GetCustomerById(Guid customerID) 7 { 8 ISession session = NHibernateHelper.GetSession(); 9 return session.Get
(customerID);10 }11 public Customer LoadCustomerById(Guid customerID)12 {13 ISession session = NHibernateHelper.GetSession();14 return session.Load
(customerID);15 }

单元测试

1         [TestMethod] 2         public void GetCustomerByIdTest() 3         { 4             Console.WriteLine("----使用Get方式获取Customer实例----"); 5             Customer c1 = _customerData.GetCustomerById(new Guid("DDF63750-3307-461B-B96A-7FF356540CB8")); 6             Assert.IsNotNull(c1); 7             Console.WriteLine("输出该客户的id信息:"); 8             Console.WriteLine(c1.CustomerID); 9             Assert.AreEqual(c1.CustomerID.ToString().ToUpper(), "DDF63750-3307-461B-B96A-7FF356540CB8");10             Console.WriteLine("输出该客户的名字:");11             Console.WriteLine(c1.NameAddress.CustomerName);12             Assert.AreEqual(c1.NameAddress.CustomerName,"wolfy");13         }14         [TestMethod]15         public void LoadCustomerByIdTest()16         {17             Console.WriteLine("----使用Load方式获取Customer实例----");18             Customer c1 = _customerData.LoadCustomerById(new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));19             Assert.IsNotNull(c1);20             Console.WriteLine("输出该客户的id信息:");21             Console.WriteLine(c1.CustomerID);22             Assert.AreEqual(c1.CustomerID.ToString().ToUpper(), "DDF63750-3307-461B-B96A-7FF356540CB8");23             Console.WriteLine("输出该客户的名字:");24             Console.WriteLine(c1.NameAddress.CustomerName);25             Assert.AreEqual(c1.NameAddress.CustomerName, "wolfy");26         }

运行单元测试,查看结果

使用ISession.Get()方法立即把对象实例保存到缓存中,使用ISession.Load()方法当你需要使用的时候再访问数据库把这个实例保存在缓存中(有点懒加载的意思,关于Lazy加载可参考前面的文章,Load方法默认是使用Lazy方式加载的)。

一级缓存管理

ISession接口为我们提供了一些常用方法来显式管理一级缓存:

ISession.Evict(object):从缓存中删除指定实例。

ISession.Clear():清空缓存。

ISession.Contains(object):检查缓存中是否包含指定实例。

在CustomerData中添加方法

1       ///  2         /// 清除session中的缓存 3         ///  4         public void ClearCache() 5         { 6             ISession session = NHibernateHelper.GetSession(); 7             session.Clear(); 8         } 9         /// 10         /// 从缓存中移除某个对象11         /// 12         /// 13         /// 
14 public void RemoveCustomerFromCache(Customer customer)15 {16 ISession session = NHibernateHelper.GetSession();17 session.Evict(customer);18 }
1    ///  2         /// session是否包含customer对象 3         ///  4         ///  5         /// 
6 public bool IsContains(Customer customer) 7 { 8 ISession session = NHibernateHelper.GetSession(); 9 return session.Contains(customer);10 }

单元测试方法

1         [TestMethod] 2         public void ManagerCacheTest() 3         { 4             //1.向ISession中添加两个Customer对象并缓存 5             Customer customer1 = _customerData.GetCustomerById(new Guid("DDF63750-3307-461B-B96A-7FF356540CB8")); 6             Customer customer2 = _customerData.GetCustomerById(new Guid("095659B0-8D3F-4DC3-8861-9D7D8A9BA570")); 7             //2.加载实例后,缓存包含两个实例 8             Assert.IsTrue(_customerData.IsContains(customer1)); 9             Assert.IsTrue(_customerData.IsContains(customer2));10             //3.从缓存中删除Customer1实例11             _customerData.RemoveCustomerFromCache(customer1);12             Assert.IsFalse(_customerData.IsContains(customer1));13             Assert.IsTrue(_customerData.IsContains(customer2));14             //4.清空ISession缓存,实例不和缓存关联15             _customerData.ClearCache();16             Assert.IsFalse(_customerData.IsContains(customer1));17             Assert.IsFalse(_customerData.IsContains(customer2));18         }

测试结果

该测试,首先加载两个customer实例,此时已将它们都存入一级缓存,首先使用RemoveCustomerFromCache方法,从缓存中将customer1对象移除,然后使用ClearCache方法清空缓存。

总结

本篇文章就到这里,一级缓存是和ISession关联的,多个Session的缓存是不能共享的。本篇文章使用了单元测试的方式进行测试,也是首次使用单元测试,也稍微研究了一下,关于单元测试的东西,算是附加学习的吧。

参考文章

转载于:https://www.cnblogs.com/wolf-sun/p/4130497.html

转载地址:https://blog.csdn.net/weixin_34008933/article/details/93244244 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python中的文件操作
下一篇:[NHibernate]N+1 Select查询问题分析

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年05月04日 22时20分01秒