2012-01-16 5 views
2

나는 엔티티는 다음과 같이 정의했다 :JPA의 EntityManager 캐싱

find 작업이 엔티티 관리자에서 수행 할 때 내가 무엇을 볼 수에서
public class Version { 
    @Id 
    private Long id; 
    private String content; 
    @Transient 
    private Model model; 

    //... 
} 

, 그것은 한 번만 기본 데이터베이스에 SELECT하게 한 다음 엔티티는 엔티티 관리자에 캐시됩니다. 그러나 model 속성에 Model을 할당하면이 변경 내용이 캐시 된 엔터티에 반영되지 않습니다. 예 : 한 호출에서 find 조작이 수행되고 Model이 지정되면 다른 EJB에서 find을 다시 호출하면 model 등록 정보가 다시 null입니다. 이 변경 사항이 캐시 된 엔티티에 반영되지 않았습니까? 아마도 @Transient일까요?

답변

7

엔티티 관리자는 첫 번째 레벨 캐시를 유지 관리하며이 첫 번째 레벨 캐시는 트랜잭션이 끝나자 마자 버려집니다. 그렇지 않으면 같은 응용 프로그램이나 다른 응용 프로그램의 다른 트랜잭션이 캐시 된 엔터티를 수정하거나 제거 할 수 있기 때문에 캐시가 부실 값을 반환합니다.

또한 동시 트랜잭션에는 각각 고유 한 세션 수준 캐시가 있으며, 따라서 동일한 엔티티의 자체 인스턴스가 있습니다.

후속 트랜잭션에서 동일한 엔터티가 find 인 경우 새 SQL 쿼리가 실행되고 엔터티의 다른 인스턴스가 반환됩니다.

주어진 엔티티에 대해 트랜잭션을 통해 무언가를 기억해야하는 경우 데이터베이스에 영구 저장해야합니다. 그것은 데이터베이스의 핵심입니다.

+0

고맙지 만 두 번째 EJB 호출에서 발급되는 새로운 SQL 쿼리 (로깅 수준이 FINEST로 설정 됨)가 표시되지 않습니다. 트랜잭션 관리가 기본값으로 설정됩니다. 그 이유는 무엇일까요? – Dario

+0

EJB1이 EJB2를 호출합니까? 아니면 클라이언트 호출 EJB1이 있습니까? 그런 다음 클라이언트가 EJB2를 호출합니까? 거래의 시작 시점과 종료 시점을 이해하고 있습니까? –

+0

웹 서비스를 통해 호출되는 EJB는 하나뿐입니다. 동일한 메소드에 대해 두 x 연속 웹 서비스 호출이 작성됩니다. 첫 번째 호출에서 로그에서'SELECT' 쿼리를 봅니다. 두 번째 호출에는 쿼리가 전혀 없습니다. – Dario

2

EclipseLink를 사용하는 경우 일시적인 공유 캐시에 병합을 두 가지 방법으로 구성 할 수 있습니다.

@CloneCopyPolicy가 사용되면 일시적인 컨텍스트의 개체가 공유 캐시에 복제되어 일시적인 필드가 보존됩니다.

@InstantiationCopyPolicy가 사용되는 경우 공유 캐시에 대한 새 인스턴스가 만들어지며 일시적 상태가 유지되지 않습니다.

위빙 및 필드 액세스를 사용하는 경우 기본값은 @CloneCopyPolicy이고, 그렇지 않으면 @InstantiationCopyPolicy입니다.

또한 DescriptorEventListener 및 postMerge/postClone 이벤트를 사용하여 공유 캐시에 병합되는 내용을 제어 할 수 있습니다.

2

@JB Nizet에 동의해야합니다. JPA의 EntityManager와 Hibernate의 Session은 확장 된 Persistence Context를 제공한다. "트랜잭션이 끝나자 마자 첫 번째 수준 캐시가 버려집니다"라는 사실은 전혀 사실이 아닙니다.

지속성 컨텍스트는 트랜잭션의 길이 거래 Scoped-- 지속성 컨텍스트 '삶'일 수도, 또는 영속 컨텍스트가 여러 트랜잭션에 걸쳐 Extended-- 수 있습니다.

https://blogs.oracle.com/carolmcdonald/entry/jpa_caching

솔루션은 그러나 올

, 당신은 당신이 캐시에 변경하고자하는 경우 오브젝트에 대한 변경 사항을 유지해야합니다.