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,以前三步配置即可实现二级缓存。

    代码下载

  • 相关阅读:
    iview table的render()函数基本的用法
    【整理】iview Tree数据格式问题,无限递归树处理数据
    【整理】用JSON-server模拟REST API
    【整理】解决vue不相关组件之间的数据传递----vuex的学习笔记,解决报错this.$store.commit is not a function
    【整理】 vue-cli 打包后显示favicon.ico小图标
    【整理】treeGrid 树形表格
    【整理】iview中刷新页面的时候更新导航菜单的active-name
    [整理] webpack+vuecli打包生成资源相对引用路径与背景图片的正确引用
    在.vue文件中让html代码自动补全的方法(支持vscode)
    解决VSCode中使用vetur插件格式化vue文件时,js代码会自动加上冒号和分号
  • 原文地址:https://www.cnblogs.com/GoodHelper/p/SpringNet_NHbernate_Prevalence.html
Copyright © 2011-2022 走看看