【问题标题】:Hibernate caching using Criteria queries使用条件查询的休眠缓存
【发布时间】:2015-04-01 04:44:12
【问题描述】:

所以,我的问题是我不确定我的查询是否被缓存。我现在的hibernate.xml使用ehcache作为二级缓存。

现在这是我的测试代码:

    Session session = HibernateUtil.getCurrentSession();
    Criteria criteria = session.createCriteria(Users.class);
    criteria.add(Restrictions.eq("id", "777008"));

    Users user = (Users) criteria.uniqueResult();

    HibernateUtil.closeCurrentSession();

    Session anotherSession = HibernateUtil.getCurrentSession();
    Criteria anotherCriteria = anotherSession.createCriteria(Users.class);
    anotherCriteria.add(Restrictions.eq("id", "777008"));

    Users anotherUser = (Users) anotherCriteria.uniqueResult();

HibernateUtil.getCurrentSession() 方法在ThreadLocal 变量中检索当前会话(如果可用)。如果会话为空,则创建一个。

HibernateUtil.closeCurrentSession()ThreadLocal 变量中获取会话,如果它不为空则关闭它。

每当我运行上面的代码(这是一个 JUnit 测试)时,我只能看到一个从数据库中选择的 Hibernate 日志。我原以为会有两个,因为我没有使用 Criteria.setCaching(true) 强制缓存任何内容。

我相信一级缓存只存在于会话范围内,二级缓存基本上是应用程序缓存。在上述两个criteria.uniqueResult() 调用的中间,我关闭了会话。

我的问题是,为什么我只看到一个 Hibernate SELECT 语句日志?我不应该看到两个吗?

此外,当我转到 hibernate.xml 并禁用二级缓存时,仍然会出现相同的输出,这让我非常困惑。

我看到的 SELECT 语句日志示例:`Hibernate: select this_.id as id8_0_, this_.nameas name8_0_, from users this_ where this_.id=?

编辑:这次我尝试了不同的方法。请参考下面的sn-p代码:

@Test
public void testCaching(){

    for (int i = 0; i < 10; i++){


        try {
            Thread.sleep(3000);

            logger.info("Retrieving user.");
            Session session = HibernateUtil.getCurrentSession();
            Criteria criteria = session.createCriteria(Users.class);
            criteria.add(Restrictions.eq("id", "777008"));
            criteria.setCacheable(true); 

            Users user = (Users) criteria.uniqueResult();

        }
        catch (Exception ex){
            System.out.println("Got it");
        }
        finally{
            HibernateUtil.closeCurrentSession();

        }
    }
}

所以,现在,每次测试调用Criteria.uniqueResult(),它都会显示一个休眠日志。所以现在,我关心的是我是否缓存了任何东西?使用此测试启用二级缓存 (ehcache)。

编辑 2:好的,现在,我有点想通为什么它没有缓存。事实证明,我必须将&lt;cache usage="read-write"/&gt; 放入对象 XML 的 &lt;class&gt; 中。但是,我不能这样做,因为其他应用程序也在使用 XML。有没有办法只在您的应用程序上启用缓存?

【问题讨论】:

    标签: java hibernate caching


    【解决方案1】:

    您会看到一个查询,因为 id=777008 的 User 对象已经在 Hibernate 上下文中。尝试使用名称字段而不是 @Id 字段进行查询,您应该会看到两个查询。

    查询缓存也可以在您的配置中全局打开,而无需为特定查询设置它。

    【讨论】:

    • 那么既然它已经在 Hibernate 上下文中,这是否意味着它被缓存了?为什么要使用名称字段?我只能使用 ID 字段进行查询。我不能真正将其全局配置为缓存,因为我不允许这样做。 hibernate.xml 也被其他应用程序使用。
    • 对不起,我的意思是,如果您使用不是基于 id 而是基于其他属性的查询,您会看到两个查询。是的,最近的对象缓存在休眠上下文中,基于 id 的搜索首先进入该上下文。因此,例如,如果您有一些@OneToMany 用户集合(除非您有批量获取),那么您将不会看到所有用户的 sql 语句,而只会看到那些尚未在上下文中的用户。
    • 嗯.. 你在 Hibernate 上下文中失去了我。我相信只有两种类型的缓存:一级缓存(会话范围)和二级缓存(应用程序范围)。你指的是哪个范围?它不能在会话范围内,因为我在第一次查询后关闭了会话。它可能不在应用程序范围内,因为当我在 Hibernate 中打开二级缓存时,我仍然得到相同的结果:/
    • 它将是与 sessionFactory(配置)相关的上下文,而不是单个会话(所以我猜它被称为应用程序范围)。
    • 好的。所以我会改变这个问题,然后问你,是否可以在特定实体上启用缓存(也许通过 SessionFactory?),因为我无法更改当前的 Hibernate 配置。 ehcache 在配置中启用,但实体没有 标签
    猜你喜欢
    • 1970-01-01
    • 2011-03-07
    • 2011-12-30
    • 2011-06-08
    • 1970-01-01
    • 2013-01-18
    • 2015-09-19
    相关资源
    最近更新 更多