首页 文章

打开Hibernate查询缓存时,默认情况下是否缓存本机SQL查询?

提问于
浏览
8

使用Hibernate 3.3.0和ehcache 1.2.3启用了二级缓存和查询缓存,我意识到以下代码在多个调用中返回相同的序列号,导致插入失败 .

HibernateCallback callback = new HibernateCallback()
        {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                StringBuilder strQuery = new StringBuilder();
                strQuery.append("SELECT ");
                strQuery.append(sequenceName);
                strQuery.append(".nextval as nextSequence FROM dual d");

                Query query = session.createSQLQuery(strQuery.toString()).addScalar("nextSequence", Hibernate.STRING);


                return query.uniqueResult();
            }
        };
        return this.hibernateTemplate.execute(callback).toString();

如果我在执行查询之前关闭查询缓存或添加以下行,则代码可以正常工作 .

query.setCacheable(false);

这很令人困惑,因为Hibernate文档明确说明了这一点

大多数查询不会从缓存中受益,因此默认情况下不会缓存查询 . 要启用缓存,请调用Query.setCacheable(true) . 此调用允许查询查找现有缓存结果,或在执行时将其结果添加到缓存中 .

在这种情况下,这种异常行为是否仍然可以假设默认情况下不缓存查询?

1 回答

  • 4

    查询缓存是一种非常简单的机制,可以存储某些密钥的结果 . 在本机查询的情况下,密钥将是您的查询本身和所有参数 .

    因此,例如,密钥可能是:

    *----------------------------------------------------------------------------------------*
    |                                    Query Cache                                         |
    |----------------------------------------------------------------------------------------|
    | ["select * from table as t where t.id=? and p.column=?", [ 1 , "value"] ] -> [  2 ] ]  |
    *----------------------------------------------------------------------------------------*
    

    从这个角度来看,每个查询都可以缓存 - 在某些情况下 . 当然,查询必须由Hibernate类处理,而不是直接通过JDBC连接 .

    而且,BTW,它's easy to find out whether your query will use the query cache or not! It'全部在 org.hibernate.cache 下的日志文件中 .

    所有这些都有一个很大的问题 - 如果你运行你的原生查询,它将驱逐二级缓存的所有实体和记录!至少它直到我使用的最后一个版本!所以你可以直接使用本机查询,但由于Hibernate无法决定它们做什么,它将清除缓存以避免此查询所做的数据更改未反映在缓存对象中 .

    因此查询缓存存在很多问题,您应该考虑是否真的想要使用该功能! Take a look at this articlethis one . 我试图避免在我的工作中使用查询缓存,我只使用SLC实体...

相关问题