2012-07-31 2 views
1


나는이 문제로 며칠 동안 벽에 머리를 두드렸다.Hibernate Infinispan 엔티티/쿼리 캐싱

우리는 Infinispan을 사용하여 Hibernate의 2 차 수준 캐시를 구현하려고합니다. 응용 프로그램은 JBoss AS 6에서 실행되며 JTA 트랜잭션을 사용합니다. 우리의 persistence.xml에

우리는이 :

: 이것은 우리가 다음을 수행하기 위해 필요한 캐시의 종류에 대한 우리의 이해에 here:

을 정의

... 
<!-- JTA configurations --> 
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" /> 
<property name="current_session_context_class" value="jta" /> 

<!-- Infinispan configurations --> 
<property name="hibernate.cache.use_second_level_cache" value="true" /> 
<property name="hibernate.cache.use_query_cache" value="true" /> 

<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.InfinispanRegionFactory"/> 
<property name="hibernate.cache.infinispan.cachemanager" value="java:CacheManager/entity"/> 
... 

로 사용 사례 1 : 참조 데이터를 보유 할 데이터베이스에 대한 레코드가 있습니다. 이 데이터는 오랜 시간 동안 변경되지 않습니다 (우리는 희망합니다 :).

이 레코드는 많이 쿼리 될 가능성이 있으므로 캐시하고 싶습니다. 사용자가이 데이터를 쿼리 할 때 캐싱해야하므로 DB로 갈 필요가 없습니다.

이 경우 캐시 유형 쿼리 캐시 또는 엔터티 캐시입니까? 쿼리가 항상 같기 때문에 큐 쿼리는 항상 동일한 결과를 반환하기 때문에 쿼리 캐시라고 생각합니다.

내 쿼리 :

List<MyEntity> list = session.createCriteria(MyEntity.class) 
     .add(Restrictions.eq("id", 1)) 
     .setCacheable(true) 
     .list(); 

사용 사례 2 : 사용자가 DB에서 특정 레코드를 가져, 그는 그것을 업데이트 할 수 있습니다. 이 엔티티 (또는 엔티티 목록)를 사용자의 세션 (로그인 세션) 캐시에 저장하여 클라이언트에서이 엔티티를 업데이트 한 경우 업데이트 전에 select를 수행 할 필요가 없습니다. 이 경우 특정 엔티티를 저장하기 때문에 엔티티 캐싱으로 간주됩니다. 맞습니까? 우리가 들어

을 저장하려면 우리가 사용하고 있습니다 :

@Cacheable (true) 
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
public class MyEntity implements Serializable 
{ 
... 
} 

오전 내가 올바르게 이러한 가정을? 그렇지 않다면, 여기에 접근은 무엇입니까? 나는이 일에서 큰 실수를하고 있다고 생각한다.

답변

1

2 차 (엔티티) 캐시는 id에 대한 맵 기반을 키로 만듭니다 (더 간단하게 만듭니다). 따라서 각 참조 데이터가 다른 엔티티에서 "참조"되면 엔티티 관리자는 먼저 DB에 가기 전에 캐시에 캐시가 있는지 확인합니다.

쿼리 캐시는 쿼리의 결과 (ID) 엔터티 캐시입니다. 그런 다음 ID를 기반으로 해당 엔티티 (바람직하게 엔티티 캐시 ...)를 검색하므로 엔티티가 2 차 캐시에 캐시되어 유용 할 필요가 있습니다.

먼저 사례, 참조 데이터를 사용하십시오. 엔티티에 캐시 가능으로 주석을 추가하고 읽기 전용 전략을 사용해야합니다. 엔티티 관리자는 참조 데이터를로드 할 때 참조 자 엔티티에 넣거나, find (clazz, id)를 사용하여 2 차 레벨 캐시에서 참조 데이터를 가져옵니다.

사례 2는 좀 더 까다 롭습니다. "세션"범위 캐시가 없습니다 (사용자 세션에 중간 결과 바인딩을 유지해야하는 경우 SFSB 또는 상위 수준 세션 메커니즘을 통해 자체를 관리해야합니다).캐시 할 수있는 엔티티를 서버의 모든 사용자에 대해 캐싱하도록 만들면 엔티티 관리자 컨텍스트는 사용자와 직접 연결되지 않습니다.

업데이트하기 전에 선택을하지 않으려면 확장 된 지속성 컨텍스트를 통해 엔티티가 관리되지 않는 상태 (병합을 방지하기 위해)에 도달하지 못하게해야합니다. 엔티티가 여러 사용자에 의해 자주 갱신 될 수있는 경우, DB가 수행하는 것보다 일관성을 관리하는 데 더 많은 시간이 걸리기 때문에 성능이 저하 될 수 있습니다.

퍼포먼스 보틀 목을 얻으려면 관련 엔티티 가져 오기 및 전달 주석이 있어야합니다. 너무 큰 경우 요청 및/또는 DB에서 너무 많은 데이터를 업데이트해야합니다.

+0

나는 아직도 모든 대답을 동화하려고합니다. 그리고 또 다른 질문이 있습니다. 첫 번째 사용 사례의 경우 다른 참조 데이터 개체 (레코드)를 DB에 추가하면 어떻게됩니까? (동일한 응용 프로그램 사용)? 캐시가 쿼리의 결과가 변경되었음을 알게되고 다음에 선택이 수행되면 DB로 이동합니까? –

+0

유지할 때 캐시에 넣을 지 모르겠습니다. 트리거로 인해 일부 데이터가 변경 될 수 있으므로 아마 선택을 할 것입니다. 어떤 식 으로든 최대 하나를 선택하고 캐시에 넣습니다. – Kazaag

+0

이 게시물에 대한 자세한 내용은 http://www.javalobby.org/java/forums/t48846.html에서 확인할 수 있습니다. – Kazaag