java – 如何正确使用getHibernateTemplate().setCacheQueries()?

在我们的一些代码中,我们使用的是HibernateDaoSupport的setCacheQueries()方法.起初我们有一个函数getByGroupId(),只调用setCacheQueries(true),但在进行集成测试时,这会导致Hibernate抛出“重复异常”.
所以我用Google搜索了一下,看到很多人使用了一种模式,他们在执行查询之前启用了缓存,然后禁用了它.然后我尝试在查询后禁用缓存,并且复制错误消失了.现在我想知道这个模式到底是做什么的?下面的代码是在此模式之后建模的.

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class MyDao extends HibernateDaoSupport{

  public List getByGroupId(Long groupId) {
    getHibernateTemplate().setCacheQueries(true);
    List result = getHibernateTemplate().find(
                    "from Selection where groupId = ? order by sortOrder ASC", groupId);
    getHibernateTemplate().setCacheQueries(false);
    return result;
  }
}

我不确定Spring和Hibernate如何在这里一起工作.如果setCacheQueries(false)将清空所有缓存的查询,那就毫无意义,但如果它只是禁用后续查询的缓存(直到调用setCacheQueries(true)),那么它会更有意义.

>这种在查询正常之前和之后打开/关闭缓存的模式是什么?
>它是否有效(即缓存的查询)?
>知道为什么在查询后不调用setCacheQueries(false)时会导致Hibernate抛出有关重复条目的异常?

解决方法:

当HibernateTemplate的cacheQueries属性为true时,它会自动使每个Query或Criteria执行可缓存.即它在执行查询/条件之前调用Query.setCacheable(true)和Criteria.setCacheable(true).

因此,您的模式实际上是使您要执行的查询可执行缓存,然后将该标志重置为false,以便下一个查询不会被缓存.

问题是如果多个线程使用HibernateTemplate,则使用此模式的结果是不确定的.您可能有一个线程将该标志设置为true,然后另一个线程立即将其重置为false,然后第一个线程有时间执行其查询.由于对属性的访问不同步,因此您可能也存在可见性问题.

我只会在创建HibernateTemplate时使用HibernateTemplate.setCacheable(true),以确保它执行的所有查询都是可缓存的.如果您不想要它,那么使用两个不同的HibernateTemplate实例(一个启用缓存,另一个不启用),或者在需要不同的缓存行为时直接使用Hibernate API.

关于您的异常,在不知道用例,确切异常及其堆栈跟踪的情况下,很难诊断.

上一篇:如何在同一个ehCache中缓存2个不同的bean方法?


下一篇:Spring Cache Abstraction