一级缓存与二级缓存


一级缓存

为了获得更好的性能,NHibernate智能地缓存数据。NHibernate有不同的缓存机制起作用,最重要的就是一级缓存。sess每个ion对象维持一个一级缓存,session对象创建时缓存创建,session对象释放时缓存销毁。

缓存只不过是一个哈希表。哈希表根据唯一键存储值,值可以根据唯一键检索。

一个实体由它的ID唯一标识,如果两个实体类型相同,ID也相等,那么这两个实体是相等的。NHibernate要求两个相同类型的对象不能有相同的ID。原因是,如果允许系统有相同ID的两个实例,那么就会将系统置于不一致的状态中。有了这个条件,NHibernate就可以执行下面的操作了:

NHibernate session对象从数据库中加载指定ID的实体,然后放到一级缓存中,访问该实体的键是它的ID值。当系统再次从数据库中加载同一个实体时,session对象首先检查它的缓存,如果实体已经存在于缓存中,NHibernate就返回缓存的实例。只有实体不在缓存时,NHibernate session对象才从数据库中加载实体。看下面的过程:

A步骤:

  • 程序请求session ID为1的product
  • session问一级缓存:“有ID为1的product吗?”
  • 一级缓存回答说:“没有”
  • session就从数据库中加载ID为1的product
  • session将product放入一级缓存,键为product的ID值
  • session返回给程序product实例
  • 程序执行更多的操作
  • 程序再次请求session ID为1的product
  • session问一级缓存:“有ID为1的product吗”
  • 一级缓存回答说:“有”
  • session就使用ID作为键从缓存中加载ID为1的product,并返回给程序

证明:

 

从上面执行结果可以得出结论:

session.Get<EmployeeInfo>(1);一共获取数据为a b c d四次,但实际操作数据库存仅为次,从而证明了上述的A步骤 正确性

从第二步可以证明:最重要的就是一级缓存。每个session对象维持一个一级缓存,session对象创建时缓存创建,session对象释放时缓存销毁。

 

二级缓存

我们已经看到NHibernate提供了非常有效的方式缓存数据。可惜,一级缓存绑定到session对象,也就是说每次session被释放,所有的缓存数据就会丢失。二级缓存定义在session工厂级别的,只要session工厂没有被释放缓存就一直存在。一旦实体加载,二级缓存就被激活,实体对所有的session(同session工厂的)都可用。这样,只要实体在二级缓存中,NHibernate就不会从数据库加载实体,直到它从缓存中移除。

测试代码验证:

 1  public static void TextSecondCache()
 2         {
 3             ISessionFactory sessionFactory = CreateISessionFactoryByXml();
 4             Console.WriteLine("第一个session开始");
 5             using (ISession session = sessionFactory.OpenSession())
 6             {
 7                 EmployeeInfo a = session.Get<EmployeeInfo>(1);
 8                 Console.WriteLine("a " + a.EmpName);
 9              
10             }
11 
12             Console.WriteLine("第一个session结束 第2个session开始");
13             using (ISession session = sessionFactory.OpenSession())
14             {
15                 EmployeeInfo a = session.Get<EmployeeInfo>(1);
16                 Console.WriteLine("a " + a.EmpName);
17             }
18 
19         }

没有开启二级缓存执行情况: 一共执行了二次SQL

 

开启二级缓存的情况

第一次执行:只执行了一次SQL操作

 

第二次执行:没有执行SQL,直接在SQL中获取查询对象

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM