【问题标题】:Hibernate 2nd Level caching doesnt seem to be workingHibernate 2nd Level 缓存似乎不起作用
【发布时间】:2011-03-09 17:21:41
【问题描述】:

我目前正在尝试使用 hibernate 附带的缓存提供程序让 hibernate 工作。

net.sf.ehcache.hibernate.SingletonEhCacheProvider

我在我的 hibernate.cfg.xml 文件中引用的 ecache.xml 中启用了一个默认缓存和一个特定于类的缓存。类/映射文件特定的缓存被定义为处理多达 20000 个对象。

但是,自从我在其中一个映射文件上打开缓存映射后,我没有看到任何性能提升。

我的测试如下。

加载 10000 个正在测试的特定映射文件的对象(这应该会影响数据库并成为瓶颈)。 接下来我要加载相同的 10000 个对象,因为此时我希望缓存被命中并看到显着的性能提升。已尝试在我正在测试的休眠映射 xml 文件上同时使用“只读”和“读写”缓存映射。

我想知道我需要做些什么来确保在加载对象时缓存在数据库之前被命中?

作为测试的一部分,请注意使用类似于下面的方法对这 10000 条记录进行分页(一次分页 1000 条记录)。

Criteria crit = HibernateUtil.getSession() .createCriteria( persistentClass );
       crit.setFirstResult(startIndex);
       crit.setFetchSize(fetchSize);
       return crit.list();

已经看到标准有一个缓存模式设置器 (setCacheMode()),那么我应该对此做些什么吗?

我注意到使用下面的统计代码,内存中有 10000 个对象(我想是冬眠脱水的对象??),但是 出于某种原因,我得到 0 次命中,更令人担忧的是 0 次未命中,因此即使统计代码似乎告诉我内存中有 10000 个对象,它在进行查找时看起来也根本不会进入缓存。

关于我在做什么的任何想法?我认为我得到未命中的事实很好,因为这意味着正在使用缓存,但我无法弄清楚为什么我没有得到任何缓存命中。这是否取决于我使用setFirstResult()setFetchSize() 的事实。

System.out.println("Cache Misses = " + stats.getSecondLevelCacheMissCount());
System.out.println("Cache Hits Count = " + stats.getSecondLevelCacheHitCount());

System.out.println("2nd level elements in mem "+ stats.getSecondLevelCacheStatistics("com.SomeTestEntity").getElementCountInMemory());

【问题讨论】:

    标签: java hibernate orm caching second-level-cache


    【解决方案1】:

    二级缓存适用于“按主键查找”。对于其他查询,您需要缓存查询(前提是启用了查询缓存),在您的情况下使用Criteria#setCacheable(boolean)

    Criteria crit = HibernateUtil.getSession().createCriteria( persistentClass );
    crit.setFirstResult(startIndex);
    crit.setFetchSize(fetchSize);
    crit.setCachable(true); // Enable caching of this query result
    return crit.list();
    

    我建议阅读:


    如果我缓存查询,它们是否都是来自查询的休眠实体,然后在二级缓存中可用?

    是的,他们会的。这在我提到的链接中进行了黑白解释:“请注意,查询缓存不会缓存结果集中实际实体的状态;它只缓存标识符值和值类型的结果。所以查询缓存应始终与二级缓存结合使用”。你读了吗?

    因为我的印象是使用查询缓存与使用休眠二级缓存完全不同。

    它是不同的(用于缓存条目的“键”不同)。但是查询缓存依赖于 L2 缓存。

    从您的回答看来,您似乎暗示查询缓存和二级缓存都是相同的,并且要生成缓存命中,我需要使用“按主键查找”。

    我只是说您需要缓存查询,因为您不是“按主键查找”。我不明白什么是不清楚的。您是否尝试在查询或条件对象上调用 setCacheable(true)?很抱歉坚持,但是您看过我发布的链接吗?

    【讨论】:

    • 所以除非与“按主键查找”一起使用,否则永远不能使用清除二级缓存?是否 crit.list(); (如果为 is 实体启用缓存)在示例代码中填充二级缓存?如果是这样,那么我只能在使用相当于“按主键查找”的 hiberanet 时访问缓存??
    • @John 正如我在回答中所写,您需要缓存查询。有什么不清楚的地方?
    • 我还是有点困惑。如果我缓存查询,那么查询中的所有休眠实体是否都可以在二级缓存中使用?因为我的印象是使用查询缓存与使用休眠二级缓存完全不同。从您的回答中,您似乎暗示查询缓存和二级缓存都是相同的,并且要生成缓存命中,我需要使用“按主键查找”。
    • @John:我已经更新了我的答案以澄清这些问题。希望它更清楚。
    猜你喜欢
    • 1970-01-01
    • 2011-10-19
    • 2011-09-03
    • 1970-01-01
    • 2018-06-07
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多