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

摘要

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

1. NHibernate二级缓存查询

NHibernate二级缓存查询是指NHibernate将查询记录的集合放到二级缓存中,之后每次查询都可以从二级缓存中拿查询记录信息。

二级缓存使用步骤:

1)在hibernate.cfg.xml文件中,使用cache.use_query_cache定义使用二级缓存查询:<property name="cache.use_query_cache">true</property>

2)在代码中显示地使用IQuery.SetCacheable(true)方法,第一次使用这个方法时,将查询条件和查询结果组成一个字典对象放入二级缓存中,字典的键是查询条件,值是查询结果记录集合。在第二次使用同样查询条件查询时再次调用这个方法,NHibernate直接从二级缓存中读取。如果查询结果记录集合在第一次调用SetCacheable后有变化(添加、修改、删除),则会清空二级缓存中的字典对象,第二次查询从数据库查询。

二级缓存查询有多种定义方式:

1)显示启用缓存查询

只使用IQuery.SetCacheable(true)方法。

程序演示

修改hibernate.cfg.xml文件,添加<property name="cache.use_query_cache">true</property>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.connection_string_name">default</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
    <property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider</property>
    <property name="cache.use_second_level_cache">true</property>
    <property name="cache.use_query_cache">true</property>
    <mapping assembly="NHibernateDemoApp"/>
    <class-cache class="NHibernateDemoApp.Customer,NHibernateDemoApp" usage="read-write"/>
  </session-factory>
</hibernate-configuration>

修改Main函数

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             using (var session = SessionFactory.OpenSession())
 6             {
 7                 IList<Customer> customers = session.CreateQuery("from Customer c where c.Id > 1")
 8                     .SetCacheable(true) 
 9                     .List<Customer>();
10                 Console.WriteLine("list count: {0}", customers.Count);
11             }
12 
13             using (var session = SessionFactory.OpenSession())
14             {
15                 IList<Customer> customers = session.CreateQuery("from Customer c where c.Id > 1")
16                     .SetCacheable(true)
17                     .List<Customer>();
18                 Console.WriteLine("list count: {0}", customers.Count);
19             }
20 
21             Console.WriteLine("Completed");
22             Console.ReadLine();
23         }

打开NHibernateProfile,执行程序,监控结果:

第一次查询后将结果存入二级缓存,第二次查询直接从二级缓存中读取。

2)指定命名缓存区域

在代码中显示调用session.SetCacheRegion方法给二级缓存结果一个强命名。

程序演示

修改Main函数

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             using (var session = SessionFactory.OpenSession())
 6             {
 7                 IList<Customer> customers = session.CreateQuery("from Customer c where c.Id > 1")
 8                     .SetCacheable(true)
 9                     .SetCacheRegion("customer_chache")
10                     .List<Customer>();
11                 Console.WriteLine("list count: {0}", customers.Count);
12             }
13 
14             using (var session = SessionFactory.OpenSession())
15             {
16                 IList<Customer> customers = session.CreateQuery("from Customer c where c.Id > 1")
17                     .SetCacheable(true)
18                     .SetCacheRegion("customer_chache")
19                     .List<Customer>();
20                 Console.WriteLine("list count: {0}", customers.Count);
21             }
22 
23             Console.WriteLine("Completed");
24             Console.ReadLine();
25         }

清空NHibernateProfile监控记录,执行程序,得到结果

3)命名查询

在实体关系映射配置文件hibernate.cfg.xml中,定义二级缓存的命名查询。

<query cacheable="true" cache-mode="normal" name="自定义名称">
  Hibernate Query Language查询字符串
</query>

cache-mode一般使用normal(默认方式),从二级缓存中读写。

cache-mode有五个枚举值

  • Ignore:不使用二级缓存
  • Put:只向二级缓存写数据
  • Get:只向二级缓存读数据
  • Normal:向二级缓存读和写数据
  • Refresh:每次强制刷新二级缓存

程序演示

修改Customer.hbm.xml文件

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateDemoApp" namespace="NHibernateDemoApp">
 3   <class name="Customer" table="Customer">
 4     <id name="Id">
 5       <generator class="native"/>
 6     </id>
 7     <property name="FirstName" not-null="true"/>
 8     <property name="LastName" not-null ="true"/>
 9     <property name="AverageRating"/>
10     <property name="Points"/>
11     <property name="HasGoldStatus"/>
12     <property name="MemberSince"/>
13     <property name="CreditRating" type="CustomerCreditRating"/>
14     <property name="Street"/>
15     <property name="City"/>
16     <property name="Province"/>
17     <property name="Country"/>
18   </class>
19   <query cacheable="true" cache-mode="normal" name="select_customer">
20     from Customer
21   </query>
22 </hibernate-mapping>

修改Main函数

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             using (var session = SessionFactory.OpenSession())
 6             {
 7                 IList<Customer> customers = session.GetNamedQuery("select_customer")
 8                     .List<Customer>();
 9                 Console.WriteLine("list count: {0}", customers.Count);
10             }
11 
12             using (var session = SessionFactory.OpenSession())
13             {
14                 IList<Customer> customers = session.GetNamedQuery("select_customer")
15                     .List<Customer>();
16                 Console.WriteLine("list count: {0}", customers.Count);
17             }
18 
19             Console.WriteLine("Completed");
20             Console.ReadLine();
21         }

清空Profile,执行程序得到结果

2. NHibernate二级缓存管理

NHibernate二级缓存由SessionFactory管理,SessionFactory提供了多个删除二级缓存内容的方法。

  • Evict:从二级缓存中删除类实例
  • EvictEntity:从二级缓存中删除指定实例
  • EvictCollection:从二级缓存中删除集合
  • EvictQueries:从二级缓存中删除查询

程序演示

修改Main函数

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             using (var session = SessionFactory.OpenSession())
 6             {
 7                 var customer = session.Get<Customer>(1);
 8             }
 9             SessionFactory.Evict(typeof(Customer));
10             using (var session = SessionFactory.OpenSession())
11             {
12                 var customer = session.Get<Customer>(1);
13             }
14 
15             Console.WriteLine("Completed");
16             Console.ReadLine();
17         }

清空NHibernateProfile的Session,执行程序得到结果

也可以强制调用session.SetCacheMode(CacheMode.Refresh),刷新二级缓存内容,第二个session查询时,session重新查询数据库。

程序演示

修改Main函数

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             using (var session = SessionFactory.OpenSession())
 6             {
 7                 IList<Customer> customers = session.CreateQuery("from Customer c where c.Id > 1")
 8                      .SetCacheable(true)
 9                      .SetCacheRegion("customer_chache")
10                     .List<Customer>();
11                 Console.WriteLine("list count: {0}", customers.Count);
12             }
13             
14             using (var session = SessionFactory.OpenSession())
15             {
16                 IList<Customer> customers = session.CreateQuery("from Customer c where c.Id > 1")
17                      .SetCacheable(true)
18                      .SetCacheRegion("customer_chache")
19                      .SetCacheMode(CacheMode.Refresh)
20                     .List<Customer>();
21                 Console.WriteLine("list count: {0}", customers.Count);
22             }
23 
24             Console.WriteLine("Completed");
25             Console.ReadLine();
26         }

执行结果,第二次强制查询数据库

原文地址:https://www.cnblogs.com/uncle_danny/p/5638039.html