2015-01-27 4 views
3

Hibernate의 @NaturalId를 사용하여 객체를 찾는 것이 유리한가요?Hibernate의 @NaturalId를 사용하는 객체를 찾은 이점

나는 Hibernate가 @NaturalId를 사용하여 객체를 얻기 위해 두 개의 쿼리를 수행한다는 사실에 우려하고있다. 첫 번째 쿼리는 실제 객체를로드하기위한 id와 두 번째 쿼리를 가져옵니다.

미리 감사드립니다.

답변

4

this article에서 설명한 것처럼 캐시를 사용하면 데이터베이스를 치지 않고도 엔터티를 확인할 수 있습니다.

ResolveNaturalIdEvent 이벤트가 발생하면, 최대 절전 모드로하려고합니다 :

  • 로드 1 레벨 캐시에서 관련 엔티티 ID
  • 로드 (활성화 된 경우) 2 레벨 캐시에서 관련 엔티티 ID
  • 데이터베이스 쿼리에
  • 가을 - 다시 1 레벨 캐시는 우리의 요청을 만족시킬 수없는 경우

    Serializable entityId = resolveFromCache(event); 
    if (entityId != null) { 
        if (traceEnabled) 
         LOG.tracev("Resolved object in cache: {0}", 
           MessageHelper.infoString(persister, event.getNaturalIdValues(), event.getSession().getFactory())); 
        return entityId; 
    } 
    
    return loadFromDatasource(event); 
    

따라서 Persistence Context API를 통해 엔티티를로드하는 것과 동일한 이점이 있습니다 (예 : EntityManager.find()).

두 개의 쿼리가 실행될 때만 엔터티가 이미 캐시되지 않은 경우입니다 (1 차 또는 2 차 수준 캐시).

2

적어도 하나의 장점은 1 차 수준 캐시의 이점입니다. 예를 들어 이메일을 통해 사용자를로드하는 경우 (naturalid) db에서 기본 키 아이디 만 가져오고 첫 번째 레벨 캐시에있는 사용자 객체는 이미있는 경우 가져옵니다. 네트워크 데이터 전송이 적기 때문에로드 시간이 빨라집니다.

0

가 사용 @NaturalID의 또 다른 장점은 또한 당신이 natural ID를 구성하는 경우 쿼리 캐시의 사용 (I 최대 절전 모드 4.3.8에서이 대답을 내놓고있어) 관련되어 한 다음 NaturalID Restrictions#naturalId하여 개체를 쿼리 또는 Session#byNaturalId 테이블이 수정 된 경우에도 쿼리 캐시에 도달 할 수 있습니다.

Hibernate는 쿼리 캐시 항목이 upToDate 인 경우 테이블의 cache of update timestamps을 유지합니다.

UpdateTimestampsCache는 : 특정 테이블에 대한 최신 업데이트의 타임 스탬프를 추적합니다. 기본 캐시 구현의 캐시 시간 초과 값이 모든 쿼리 캐시의 시간 초과 값보다 높은 값으로 설정되는 것이 중요합니다. 실제로 기본 캐시는 만료되도록 구성하지 않는 것이 좋습니다. 특히, LRU 캐시 만기 정책이 절대로 적절하지 않음에 유의하십시오. 최대 절전 모드가 캐시 된 경우 다음과 같은 일반 영어

,

*---------------------------------------------------------- * 
|      Query Cache       |      
|---------------------------------------------------------- | 
| ["from Team where trophies = ", ["10"] ] -> [1,2] ]   | 
*---------------------------------------------------------- * 

당신이 원하는 것을 해당 ID를 가진 팀은 쿼리 새로운 트로피를 이길 경우 "팀에서 어디 트로피 = 10"가 더 더 이상 돌려 보내십시오. 이를 달성하기 위해 Hibernate는 테이블이 마지막으로 업데이트 된 시점의 레코드를 유지하고 쿼리 캐시 항목이이 타임 스탬프보다 오래된 경우 결과를 신뢰하지 않습니다.

결과가 여전히 유효하지만 Hibernate가 캐시가 엔티티별로 존재하지 않기 때문에 신뢰할 수 없다고 말하는 것은 분명한 이유입니다. 예를 들어, ID = 3 인 팀이 승격 될 경우, 1,2 팀에 대한 항목은 승격되지 않더라도 무효화됩니다. 팀 1이 양보되지만 트로피 카운트가 이전과 같을 경우 쿼리 캐시 항목도 유효하지만 무효화됩니다.

것은 우리는 우리가 그들이 UPTODATE되지 않은 경우에도 쿼리 캐시 항목에 신뢰에 최대 절전 모드로있게됩니다

List results = s.createCriteria(Citizen.class) 
       .add(Restrictions.naturalId().set("ssn", "1234").set("state", ste)) 
       .list() 

NaturalID

를 통해 조회 된 경우. "그렇습니다. 최대 절전 모드입니다. 테이블이 융기되었음을 알고 있습니다. 그러나 이러한 엔티티의 NaturalID가 변경되지 않았으므로 NaturalID에 의한 쿼리에 해당하는 항목을 신뢰할 수 있음을 확신합니다".

하이버 네이트는 쿼리가 upToDate 검사를 피할 수 있는지 알아보기 위해 몇 가지 사항을 확인해야한다. 이 Loader#getResultFromQueryCache

boolean isImmutableNaturalKeyLookup = 
        queryParameters.isNaturalKeyLookup() && // If you are querying by NaturalID 
          resultTypes.length == 1 && 
          resultTypes[0].isEntityType() && // and you are returning an Entity (no projections) 
          getEntityPersister(EntityType.class.cast(resultTypes[0])) 
            .getEntityMetamodel() 
            .hasImmutableNaturalId(); // and that Entity has an immutable NaturalID (Is the default and I can't imagine when we could use a mutable NaturalID) 

에 isImmutableNaturalKeyLookup이 Query#get에 전달 된 플래그를 볼 수 있습니다. StandardQueryCache에서 어떻게 사용되는지 보겠습니다.

final List cacheable = getCachedResults(key, session); 
final Long timestamp = (Long) cacheable.get(0); 
if (!isNaturalKeyLookup && !isUpToDate(spaces, timestamp, session)) { 
    if (DEBUGGING) { 
     LOG.debug("Cached query results were not up-to-date"); 
    } 
    return null; 
} 

return cacheable; // more or less 

isNaturalKeyLookup이 true이면 isUpToDate를 확인하지 않습니다.

Hibernate: Cache Queries the Natural Id Way은 쿼리 캐시와 NaturalID에 대한 오래된 게시물이지만이를 이해하는 데 도움이됩니다.