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

Zhi*_*Ong 8 caching hibernate ehcache

使用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();
Run Code Online (Sandbox Code Playgroud)

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

query.setCacheable(false);
Run Code Online (Sandbox Code Playgroud)

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

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

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

Łuk*_*nek 5

查询缓存是一种非常简单的机制,它存储特定键的结果。在本机查询的情况下,该键将是您的查询本身和所有参数。

例如,关键可能是:

*----------------------------------------------------------------------------------------*
|                                    Query Cache                                         |
|----------------------------------------------------------------------------------------|
| ["select * from table as t where t.id=? and p.column=?", [ 1 , "value"] ] -> [  2 ] ]  |
*----------------------------------------------------------------------------------------*
Run Code Online (Sandbox Code Playgroud)

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

而且,顺便说一句,很容易找出您的查询是否将使用查询缓存!这一切都在 下的日志文件中org.hibernate.cache

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

因此,查询缓存存在很多问题,您应该考虑是否真的想使用该功能!看看这篇文章这篇文章。我试图避免在工作中使用查询缓存,我只对实体使用 SLC...