2012-06-06 5 views
3

최대 절전 모드 엔티티를 ehcache에 저장하고 있습니다. 엔티티를 검색하기 위해 레이어를 호출 할 때 인터셉터는 해당 메소드를 호출하고 캐시합니다. 동일한 메소드가 호출 될 다음에 엔티티가 캐시에서 리턴됩니다. 이 모든 것이 잘 작동합니다.ehcache에서 최대 절전 모드 개체를로드 할 때 lazyinitialization 예외가 발생했습니다.

내 엔티티에는 FetchType.Lazy로 정의 된 몇 가지 속성 (개체 또는 연결된 엔티티)이 있습니다. 이 같은 것,

@JoinColumn(name = "inventory_item_oid", referencedColumnName = "inventory_item_oid") 
@ManyToOne(fetch = FetchType.LAZY) 
private InventoryItem inventoryItem; 

따라서 모든 속성이로드되지는 않습니다. Inventory Item이 필요할 때 호출됩니다. 이 호출은 LazyInitialization 예외를 던지고 있습니다.

캐시 된 값이 1 일 동안 저장되기 때문에 만료되기 전에 여러 번 호출 할 수 있습니다.

이러한 호출 중 하나는 위의 예외를 throw합니다.

긴 동면 세션을 사용하면이 문제를 해결할 수 있습니다. 하지만 내 요청/응답 기반 응용 프로그램 때문에 그것은 작동하지 않습니다.

InventoryItem이 Null인지 여부를 확인해야하며 Null 인 경우 해당 값을 별도로 가져 와서 부모에게 연결해야하는 또 다른 방법이 있습니다. 이것은 좋은 것처럼 보이지만 많은 실체가 있기 때문에 많은 일이 필요합니다.

게으름으로 정의 된 객체를 가져올 수있는 다른 방법이 있는지 알고 싶습니다.

답변

1

EHCache에서 엔티티를 직접 캐시해서는 안됩니다. 대신, 2 차 레벨 캐시를 사용하도록 Hibernate를 설정하고 EHCache를 구현으로 사용해야한다.

최종 결과는 동일합니다. 엔티티가 캐싱되고 데이터베이스에 왕복을 저장합니다. 하지만 2 차 레벨 캐시를 사용하면 모든 것이 투명해질 것입니다. 즉, 세션에서 엔티티를로드하면 Hibernate는이를 캐시에 자동으로 저장합니다. 그리고 만약 당신이 세션에서 그것들을 다시로드한다면, Hibernate는 그것들을 캐시로부터 얻을 것이다. 엔티티를 업데이트하면 캐시에서 제거되어 다음에 새로운 사본이 다시로드됩니다.

손으로 만든 또 다른 큰 차이점은 Hibernate가 엔터티로 반환한다는 것입니다. 그래서 만약 당신이 단지 cachedEntity.getNonCachedEntity()를 호출한다면, Hibernate는 캐쉬가 전혀없는 것처럼 캐싱되지 않은 엔티티를 정확하게 지연로드 할 것이다.

엔티티가 데이터베이스 또는 두 번째 레벨 캐시에서 온 것인지 여부는 아무것도 변경하지 않습니다. 속성이 지연로드되고 세션이 닫힌 후에이 속성에 액세스하는 경우 지연 속성은 세션이 닫히기 전에 초기화됩니다.

Hibernate.initialize(foo.getInventotyItem())을 호출하여 초기화하십시오.

자세한 내용은 Hibernate documentation.

+0

"세션이 닫힌 후에이 속성에 액세스하는 경우 세션이 닫히기 전에 지연 속성을 초기화해야합니다." 그 객체를 처음 검색 할 때 세션 밖에서 사용된다는 것을 어떻게 알 수 있습니까?! 귀하의 제안은 매회 캐시 된 객체를 초기화하여 게으른 속성을 완전히 사용하지 못하게하는 것과 같습니다. –

+0

검색 할 때 지연 속성을 초기화 할 필요가 없습니다. 나중에 액세스하려면 세션을 닫기 전에 초기화해야합니다.이 문제가 발생하지 않는 가장 쉬운 방법은 세션이 닫힌 후에 속성에 액세스하지 않는 것입니다 (예 : 엔티티 사용을 마친 경우에만 닫고 Examp에 공개 세션보기 필터 사용). 세션이 닫힌 후에 엔티티 사용을 피하십시오 (예 : 엔티티를 DTO로 변환) –

+0

좋습니다. 여기 테스트가 있습니다. 저장소 메소드를 처음으로 호출하고 초기화되지 않은 게으른 비하인드 결과가 캐시됩니다. 실이 끝났어. 다른 스레드에서 동일한 메소드를 호출하고 해당 소품을 읽으려고 시도하는 동안 Lazy Exception을 얻습니다. 왜 이것을 캐시 소프트웨어에 위임하는 대신 추가 작업 (즉, 세션을 명시 적으로 여는 작업)을해야합니까? 캐시 구성에 대한 결정이 하나 더있을 수 있습니까? –