n休眠第二级缓存在查询时不起作用
本文关键字:存在 缓存 查询 不起作用 二级 休眠 | 更新日期: 2023-09-27 18:34:13
我有以下问题。我已经在nHibernate(使用Postgres(上启用了第二级缓存系统,如下所示配置
cfg.SessionFactory().Caching.Through<RtMemoryCacheProvider>().WithDefaultExpiration(28800);
我只启用实体缓存,因为此时我不需要查询缓存。
在我的实体中,这是我的设置(它们有些是读写的,有些是只读的,此时可以设置为只读(
<id name="StudentID" access="property" column="`StudentID`">
<generator class="native" />
</id>
<property name="Name" column="`Name`" >
<property name="Address" column="`Address`" />
<property name="IsActive" column="`IsActive`" />
<property name="DateCreated" column="`DateCreated`" />
<property name="DateLastUpdated" column="`DateLastUpdated`" />
<property name="LastUpdatedBy" column="`LastUpdatedBy`" />
<set name="Projects" inverse="true" mutable="false">
<cache usage="read-only"/>
<key column="`StudentID`" />
<one-to-many class="Project" />
</set>
<set name="Classes" inverse="true" mutable="false">
<cache usage="nonstrict-read-write"/>
<key column="`StudentID`" />
<one-to-many class="Class" />
</set>
<set name="Books" inverse="true" mutable="false">
<cache usage="nonstrict-read-write"/>
<key column="`StudentID`" />
<one-to-many class="Book" />
</set>
</class>
在对我的解决方案进行单元测试时 - 我首先预取学生列表,然后尝试生成缓存命中
public bool PreLoadStudents()
{
using (ISession session = NHibernateHelper.OpenSession())
{
IList<Student> results = session.QueryOver<Student>()
.Fetch(d => d.Projects).Eager
.Fetch(d => d.Classes).Eager
.Fetch(d => d.Books).Eager
.TransformUsing(Transformers.DistinctRootEntity)
.List<Student>();
}
}
[Test]
public void GetByIdTest()
{
bool bLoaded = testBLL.PreLoadStudents();
var student1 = testBLL.GetByID("123");
var student2 = testBLL.GetByID("123");
long cacheHit = testBLL.GetSessionFactory().Statistics.SecondLevelCacheHitCount;
Assert.That(cacheHit,Is.EqualTo(2));
}
我已经尝试了两种不同的"GetByID"实现,其中一个使用约定"get"方法,另一个使用查询方法与 fetch 语句类似到预加载学生学生方法。
在"get"方法的情况下,缓存命中和测试通过。在"查询结束"的情况下,不会发生缓存命中或未命中,而是执行了 2 个查询。
这是我使用"Get"方法用于"GetByID"方法
的代码var student = session.Get<Student>(studentId);
我不喜欢这种方法,因为我无法获取延迟加载的子集合
这是我使用"QueryOver"方法用于"GetByID"方法的代码
var student = session.QueryOver<Student>()
.Where(d => d.studentId == currentStudentId)
.Fetch(d => d.Projects).Eager
.Fetch(d => d.Classes).Eager
.Fetch(d => d.Books).Eager
.SingleOrDefault();
关于为什么"get"方法生成命中而查询方法没有的任何想法?
在阅读并做了一些实验测试之后,这是我的问题出现的解决方案。
我最初的问题 - 关于为什么"get"方法产生命中而查询方法没有的任何想法?是一个错误的问题,原因如下:
- nHibernate中的二级缓存(L2(缓存实体的值
- nHibernate中的查询缓存缓存搜索结果的索引
因此
- Get 允许我们在知道 id 的情况下快速检索实体。如果我们不知道 ID,那么我们需要执行一个将命中的查询数据库(如果以前未运行过(。另一种方法是从缓存加载所有内容,然后在缓存上运行 LINQ。 查询
- 结束允许我们将查询结果存储在可以从二级缓存填充的查询缓存中。
经验 教训
- 如果要缓存查询,请同时打开 L2 缓存和查询缓存
- ,没有 L2 的查询缓存可能不会提高太多性能
- L2 只能通过缓存查询或通过 GET 访问
二级缓存仅在您有事务时才有效,这也是解决查询的良好做法。
using (ISession session = NHibernateHelper.OpenSession())
using (ITransaction tx = session.BeginTransaction())
{
IList<Student> results = session.QueryOver<Student>()
.Fetch(d => d.Projects).Eager
.Fetch(d => d.Classes).Eager
.Fetch(d => d.Books).Eager
.TransformUsing(Transformers.DistinctRootEntity)
.List<Student>();
tx.Commit();
}