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

oli*_*ren 3 java spring caching hibernate ehcache

在我们的一些代码中,我们使用的是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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

JB *_*zet 8

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

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

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

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

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