在我们的一些代码中,我们使用的是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.
关于您的异常,在不知道用例,确切异常及其堆栈跟踪的情况下,很难诊断.