2011-08-17 3 views
3

코드의 일부에서는 HibernateDaoSupport의 setCacheQueries() 메소드를 사용하고 있습니다. 처음에 우리는 setCacheQueries(true)이라고 불리는 함수 getByGroupId()을 가지고 있었지만, 통합 테스트를 할 때, 이것은 Hibernate가 "중복 예외"를 던지게했다. 그래서 나는 조금 주위에 인터넷 검색을하고 그 중 많은 사람들이 쿼리를 수행하고 나중에 비활성화하기 전에 캐시를 활성화 한 패턴을 사용함을 보았습니다. 그런 다음 쿼리 후 캐싱을 사용하지 않으려 고 시도했지만 복제 버그가 사라졌습니다. 이제이 패턴이 실제로 무엇을하는지 궁금합니다. 아래 코드는이 패턴을 모델로합니다.getHibernateTemplate()은 어떻게 사용됩니까? setCacheQueries()가 제대로 사용 되나요?

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; 
    } 
} 

여기 스프링과 하이버 네이트가 어떻게 작동하는지 잘 모르겠습니다. setCacheQueries(false)이 캐시 된 모든 쿼리를 비우면 의미가 없지만 나중에 쿼리를 캐싱하지 않으면 (setCacheQueries(true)이 호출 될 때까지) 조금 더 의미가 있습니다.

  • 쿼리를 수행하기 전후에 캐싱을 켜고 끄는 패턴이 정상입니까?
  • 작동합니까 (즉, 캐시 된 쿼리입니까?)
  • 쿼리 후 setCacheQueries(false)을 호출하지 않을 때 Hibernate가 중복 된 항목에 대한 예외를 던지게하는 이유는 무엇입니까? HibernateTemplate의의 cacheQueries 속성이 true 인 경우

답변

8

은 자동으로 각 Query 또는 Criteria는 캐시 실행합니다. 나는. 쿼리/조건을 실행하기 전에 Query.setCacheable (true) 및 Criteria.setCacheable (true)을 호출합니다.

따라서 패턴은 실제로 캐시 할 수있는 쿼리를 작성한 다음 플래그를 false로 재설정하여 다음 쿼리를 캐시 할 수 없게 만듭니다.

HibernateTemplate이 여러 스레드에서 사용되는 경우이 패턴을 사용한 결과는 불확실합니다. 스레드가 플래그를 true로 설정 한 다음 다른 스레드가 첫 번째 스레드가 해당 쿼리를 실행할 시간을 갖기 전에이를 즉시 false로 재설정 할 수 있습니다. 그리고 속성에 대한 액세스가 동기화되지 않았기 때문에 가시성 문제가있을 수도 있습니다.

모두 실행되는 쿼리가 캐시 가능하도록하려면 HibernateTemplate 생성시에만 HibernateTemplate.setCacheable(true)을 사용합니다. 원하지 않는다면 두 개의 다른 HibernateTemplate 인스턴스 (하나는 캐시를 사용하고 다른 하나는 사용하지 않음)를 사용하거나 다른 캐싱 동작을 원할 때 Hibernate API를 직접 사용하십시오.

예외와 관련하여 사용 사례, 정확한 예외 및 스택 추적을 알지 못하면 진단하기가 어렵습니다.

+0

모든 그는 말했다,하지만 당신은 쿼리 캐시의 세밀한 제어를 필요로하는 경우, 실행 [사용 : 그뿐만 아니라, 여기에 전체 템플릿 세계적으로 쿼리 쿼리 당 캐시 대신을 활성화 할 수 있습니다 방법 ] (http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/HibernateTemplate.html#execute%28org.springframework.orm.hibernate3.HibernateCallback%29) 또는 [executeFind()] (http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/HibernateTemplate.html#executeFind%28org.springframework.orm.hibernate3 .HibernateCallback % 29) 그리고 Query 객체 자체에 대한 캐싱을 가능하게합니다. –

+0

죄송합니다. 여기에 분명한 내용이 없지만 "다음 쿼리를 캐시 할 수 없도록 플래그를 false로 다시 설정하십시오."라는 메시지가 표시되면 캐시가 꺼져있을 때 캐시에서 제거 된 쿼리가 캐시 된 상태입니까? 또는 그들이 보관되고 있습니까 (단지 추가되지 않았습니까?)? 즉,이 메소드를 다음에 호출 할 때 캐시에서이 쿼리를 가져 옵니까? – oligofren

+1

스레드 안전 btw에 대한 좋은 지적! – oligofren

2

JB의 대답은 돈이다.) (

public List findBySomething(final int something) { 
    return getHibernateTemplate().execute(new HibernateCallback<List>() { 
     @Override 
     public List doInHibernate(Session session) { 
      Query query = session.createQuery("from Something where something = :something"); 
      query.setParameter("something", something); 
      query.setCacheable(true); 
      return query.list(); 
     } 
    }); 
} 
+0

좋아요. 그것이 어떻게 완료되어야하는지에 대한 예제를보기 좋다 :-) – oligofren

관련 문제