zoukankan      html  css  js  c++  java
  • NHibernate系列文章九:NHibernate对象二级缓存上

    摘要

    NHibernate的二级缓存由SessionFactory管理,由所有Session共享。

    NHibernate缓存读取顺序:

    首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并返回

    • 如果一级缓存对象不存在,则读二级缓存。
    • 如果二级缓存对象存在,则读取二级缓存里的对象并返回
    • 如果二级缓存对象不存在,则读数据库

    二级缓存一般存储不发生变化的数据,如果数据经常要进行修改删除操作,不宜使用缓存

    1. NHibernate二级缓存设置

    NHibernate的二级缓存在hibernate.cfg.xml文件中设置。

    • cache.provider_class:二级缓存提供程序。NHibernate自带二级缓存提供程序类NHibernate.Cache.HashtableCacheProvider(许多书上说实际项目中建议不要使用这个类,这里只做为示例使用它)。如果需要使用第三方NHibernate二级缓存提供类,则需要在程序里添加第三方dll引用,并在cache.provider_class指向第三方类。这些第三方缓存provider都是开源的,可以从NHibernate Contrib下载。
    • cache.use_second_level_cache:设置是否使用二级缓存
    • class-cache:为NHibernate实体类设置缓存策略,格式是:
      <class-cache class="完整类名,Assembly名称" usage="read-only|read-write|nonstrict-read-write|transactional"/>

      class是NHibernate实体类,以逗号隔开,前部分是完整的类名,后面部分是assembly名称。

      usage是并发访问策略,NHibernate内置四种并发访问策略,可以设置下面四个值:

      • read-only:只读缓存,适用于只读数据。
      • read-write:读写缓存。
      • nonstrict-read-write:非严格读写缓存,不保证缓存与数据库的一致性。
      • transactional:事务缓存,提供可重复读的事务隔离级别。

      一般只需要设置成read-only或者read-write,这篇文章第二部分介绍更新操作对二级缓存的影响。

    • 除了在hibernate.cfg.xml文件中设置class-cache指定为哪一个实体类设置二级缓存以外,也可以在实体关系映射配置文件内设置。

       设置方法是在id属性之前添加这句:<cache usage="read-only|read-write|nonstrict-read-write|transactional" />

    • 推荐统一在hibernate.cfg.xml文件中设置,后期维护更方便。

    程序演示

    修改hibernate.cfg.xml文件

    <?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>
        <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             //在两个session里两次查询相同对象
     6             using (var session = SessionFactory.OpenSession())
     7             {
     8                 var customer = session.Get<Customer>(1);
     9             }
    10 
    11             using (var session = SessionFactory.OpenSession())
    12             {
    13                 var customer = session.Get<Customer>(1);
    14             }
    15 
    16             Console.WriteLine("Completed");
    17             Console.ReadLine();
    18         }

    打开NHibernateProfile,ctrl+x清空所有Session,F5执行应用程序得到结果

    结果显示只查询了一次数据库。因为是两独立session两次查询同一个持久化对象,如果没有使用二级缓存,应该是两次查询数据库,结果跟上一篇文章一样。但是这里使用了二级缓存,二级缓存在所有ISession里共享,因此只查询一次数据库。

    NHibernateProfile的结果第二行内容,也明确表明了,第二次Get的时候是从二级缓存中读取的。

    2. 更新操作对二级缓存的影响

    更新操作对二级缓存的影响由配置项class-cache的属性usage决定,如果设置的是read-only,则数据更新后不刷新缓存。如果设置的是read-write,则数据更新后刷新二级缓存,第二次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                 Console.WriteLine("in session 1");
     8                 var customer = session.Get<Customer>(1);
     9                 Console.WriteLine("before updated: {0} {1}", customer.FirstName, customer.LastName);
    10                 customer.LastName = "Chen";
    11                 session.SaveOrUpdate(customer);
    12                 session.Flush();
    13                 Console.WriteLine("after updated: {0} {1}", customer.FirstName, customer.LastName);
    14             }
    15             
    16             using (var session = SessionFactory.OpenSession())
    17             {
    18                 Console.WriteLine("in session 2");
    19                 var customer = session.Get<Customer>(1);
    20                 Console.WriteLine("{0} {1}", customer.FirstName, customer.LastName);
    21             }
    22 
    23             Console.WriteLine("Completed");
    24             Console.ReadLine();
    25         }

    ctrl+x清空NHibernateProfile的Session,F5执行程序,得到结果

    LastName已经得到更新,第二次session查询得到了最新的记录。

     第二次session查询自动查询数据库。

  • 相关阅读:
    转载一篇关于kafka零拷贝(zero-copy)通俗易懂的好文
    kafka的一些核心理论知识
    Kafka知识点(Partitions and Segments)
    kafka: Producer配置和Consumer配置
    kafka: Java实现简单的Producer和Consumer
    SAP抛xml资料到kafka(本机模拟)
    解决方法: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation
    kafka log保存在本机的位置 kafka数据保存的位置
    Kafka: 下载安装和启动
    tomcat错误提示:指定的服务未安装。Unable to open the service 'tomcat9'的原因和解决方法
  • 原文地址:https://www.cnblogs.com/uncle_danny/p/5636134.html
Copyright © 2011-2022 走看看