NHibernate 命名查询和二级缓存

Posted

技术标签:

【中文标题】NHibernate 命名查询和二级缓存【英文标题】:NHibernate named query and 2nd level cache 【发布时间】:2009-11-03 05:55:52 【问题描述】:

我有以下映射

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="Domain.Core"
               namespace="Domain.Core">
<class name="Industry" table="INDUSTRY">
<cache usage="read-write" region="IndustryCache" include="all"/>
<id name="Id" type="Int64" column="IID">
  <generator class="sequence">
    <param name="sequence">INDUSTRY_SEQ</param>
  </generator> 
</id>
<version name="Version" column="VERSION" access="property" unsaved-value="null" generated="never"/>
<property name="CreationTime" column="CREATE_DATE" type="DateTime" not-null="true" />
<property name="CreatedBy" column="CREATE_USER" type="String" not-null="true" />
<property name="LastUpdateTime" column="MODIFY_DATE"  type="DateTime" not-null="false" />
<property name="LastUpdateBy" column="MODIFY_USER" type="String" not-null="false" />
<property name="Code" column="INDUSTRY" type="String" not-null="false" />
<map name="Resources" table="INDUSTRY_TL"  fetch="subselect">
  <cache region="IndustryCache" usage="read-write" include="all"/>
  <key column="INDUSTRY_ID"/>
  <composite-index class="Framework.Globalization.UILanguage, Framework">
    <key-property name="Code" column="LANG" access="property" />
  </composite-index>
  <composite-element class="Industry+Translation">
    <property name="Name" column="Industry_TL" />
  </composite-element>
</map>
</class>
<query name="GetIndustyOrderByName">
<![CDATA[
from Industry as i left join fetch i.Resources as res where INDEX(res) = :lang order  
by res.Name
]]>
</query>    
</hibernate-mapping>

以及hibernate.cfg.xml中的如下配置

<property name="show_sql">true</property>
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
<property name='prepare_sql'>true</property>
<property name='query.substitutions'>Y=true,N=false,0=false,1=true</property>
<property name="generate_statistics">true</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">Framework.Cache.SossCacheProvider, Framework.Cache.SossNHibernateCache</property>
<property name="cache.use_query_cache">true</property>

现在,当我使用调用映射集合的 SetCacheable(true) 运行命名查询时,它不会到达二级缓存。有什么原因吗?

更一般地说,有没有办法将命名查询的结果集放入二级缓存?

谢谢!

【问题讨论】:

【参考方案1】:

为了让查询使用二级缓存,必须做两件事: 1. 在 NHibernate 配置中启用查询缓存:

    <property name="cache.use_query_cache">true</property>

2。获取IQuery实例时开启缓存查询:

    IQuery = session.GetNamedQuery("from Industry as i left join fetch i.Resources as res where INDEX(res) = :lang order by res.Name")
      .SetCacheable(true)
      .Setxxx();

这些设置会导致查询结果被放入二级缓存。但是二级查询缓存只存储实体的标识符,而不是实体本身。为了使查询的执行完全避开数据库,实体也必须被缓存。有关二级缓存交互的更多说明,请参阅NH Docs。

【讨论】:

我确实设置了所有这些,NHProf 告诉我我没有达到二级缓存。唯一的区别是缓存的名称是在 hbml.xml 文件中而不是在代码中定义的。 我认为需要更多细节。 Industry 类和 NH 配置文件的完整映射将是一个好的开始。

以上是关于NHibernate 命名查询和二级缓存的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate第三方二级缓存bug

Mybatis源码剖析:二级缓存源码剖析

mybatis0209 二级缓存

MyBatis从入门到精通—源码剖析之二级缓存细节

23mybatis学习——mybatis的二级缓存

MyBatis二级缓存带来的问题