zoukankan      html  css  js  c++  java
  • Spring.NET实用技巧1——基于Prevalence下的NHibernate二级缓存使用技巧

      什么是二级缓存?

      NHibernate的Session提供了一级缓存。每个Session,对同一个id进行两次Load,不会发送两条SQL语句给数据库,但是Session一但关闭,一级缓存也就失效了。

       与Session相对的是,SessionFactory也提供了相应的缓存机制。

      SessionFactory缓存可以依据功能和目的的不同而划分为内置缓存和外置缓存。

      SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的副本,而预定义SQL语句是在NHibernate初始化阶段根据映射元数据推导出来的。

      SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,

      因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的副本,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的二级缓存。

      NHibernate的二级缓存的实现原理与一级缓存是一样的,也是通过以ID为key的Map来实现对对象的缓存。 由于NHibernate的二级缓存是作用在SessionFactory范围内的,是一种全局缓存,因而它比一级缓存的范围更广,可以被所有的Session对象所共享。


      二级缓存的工作内容

           NHibernate的二级缓存同一级缓存一样,也是针对对象id来进行缓存。所以说,二级缓存的作用范围是针对根据id获得对象的查询。

           二级缓存的工作可以概括为以下几个部分:

     在执行各种条件查询时,如果所获得的结果集为实体对象的集合,那么就会把所有的数据对象根据id放入到二级缓存中。

     当NHibernate根据id访问数据对象的时候,首先会从Session一级缓存中查找,如果查不到并且配置了二级缓存,那么会从二级缓存中查找,如果还查不到,就会查询数据库,把结果按照id放入到缓存中。

     删除、更新、增加数据的时候,同时更新缓存。

      缓存策略
      只读缓存(read-only),读/写缓存(read-write),不严格的读/写缓存(nonstrict-read-write)

      下面我就针对二级缓存的使用场景举个例子:在操作数据库的时候,常会用到事务。在使用事务begin tran而没有立刻执行commit或者rollback的时候,查询表中的数据,这时有些数据将无法获取,只有等到事务执行完毕时才会查询出这些数据。如果有长事务,甚至会出现“超时”的现象。(见下图)

      换句话说,当数据库服务器遇到大并发时,没有缓存机制是很可怕的。而一级缓存仅仅只是针对Session,为了解决这类问题,则需要一种全局的缓存——二级缓存。配置了二级缓存后,查询和伴随事务的增删改操作将不受影响。

      NHibernate的二级缓存组建有MemCache、Prevalence、SharedCache、SysCache、SysCache2、Velocity。今天主要介绍Prevalence的使用。

      1.加入Bamboo.Prevalence.dll、Bamboo.Prevalence.Util.dll、NHibernate.Caches.Prevalence.dll这三个程序集。

      下载地址 http://sourceforge.net/projects/nhcontrib/files/

       2.在NHibernate的映射文件加入节点<cache usage="read-write"/>的配置项。

       3.配置Spring.Data.NHibernate.LocalSessionFactoryObject对象的HibernateProperties属性:

        ⑴.加入<entry key="cache.use_second_level_cache" value="true"/>,启用二级缓存。

        ⑵.加入<entry key="expiration" value="300" />,设置二级缓存的有效时间,默认情况为300秒。

        ⑶.加入<entry key="prevalenceBase" value="d:\cache" />,设置物理缓存文件的存放位置,

          注意的是目前不支持相对路径,不然在开发环境会加到IDE的目录下,在部署时会加到system32/inetsrv/下。

    hibernate-mapping
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain">
      
    <class name="Domain.Department, Domain" table="T_Department" lazy="true" >
        
        
    <cache usage="read-write" />
        
        
    <id name="DepartmentID" column="DepartmentID" type="Int32" >
          
    <generator class="native" />
        
    </id>

        
    <property name="Name" type="String">
          
    <column name="Name" length="50" not-null="true"></column>
        
    </property>


        
    <bag name="PersonList" inverse="true" lazy="true" generic="true" cascade="all-delete-orphan" table="T_Person">
          
    <cache usage="read-write" />
          
    <key column="DepartmentID" foreign-key="FK_Person_Department"/>
          
    <one-to-many class="Domain.Person, Domain" />
        
    </bag>

      
    </class>
    </hibernate-mapping>
    NHibernate Configuration
      <!-- NHibernate Configuration -->
      
    <object id="NHibernateSessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate21">
        
    <property name="DbProvider" ref="DbProvider"/>
        
    <property name="MappingAssemblies">
          
    <list>
            
    <value>Domain</value>
          
    </list>
        
    </property>
        
    <property name="HibernateProperties">
          
    <dictionary>
            
    <entry key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
            
    <entry key="dialect" value="NHibernate.Dialect.SQLiteDialect"/>
            
    <entry key="connection.driver_class" value="NHibernate.Driver.SQLite20Driver"/>
            
    <!--<entry key="dialect" value="NHibernate.Dialect.MsSql2005Dialect"/>
            <entry key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
    -->
            
    <entry key="use_outer_join" value="true"/>
            
    <entry key="show_sql" value="true"/>
            
    <entry key="hbm2ddl.auto" value="update"/>
            
    <entry key="query.substitutions" value="true 1, false 0, yes 'Y', no 'N'"/>
            
    <entry key="proxyfactory.factory_class" value="NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu"/>

            
    <entry key="cache.use_second_level_cache" value="true"/>
            
    <entry key="cache.default_expiration" value="300"/>
            
    <entry key="prevalenceBase" value="cache" />
            
    <entry key="expiration" value="300" />
            
    <entry key="cache.provider_class" value="NHibernate.Caches.Prevalence.PrevalenceCacheProvider, NHibernate.Caches.Prevalence"/>
          
    </dictionary>
        
    </property>

        
    <!-- provides integation with Spring's declarative transaction management features -->
        
    <property name="ExposeTransactionAwareSessionFactory" value="true" />


      
    </object>

    OK,以前三步配置即可实现二级缓存。

    代码下载

  • 相关阅读:
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    PHP extract() 函数
    PHP end() 函数
    PHP each() 函数
    PHP current() 函数
  • 原文地址:https://www.cnblogs.com/GoodHelper/p/SpringNet_NHbernate_Prevalence.html
Copyright © 2011-2022 走看看