2010-05-11 5 views
37

JPA (eclipselink)를 사용하여 데이터베이스에서 데이터를 가져오고 싶습니다. 데이터베이스는 다른 여러 소스로 변경되므로 필자가 수행 한 모든 검색에 대해 데이터베이스로 돌아가고 자합니다. 나는 캐시를 비활성화하는 것에 관한 많은 게시물을 읽었지만 이것이 효과가없는 것 같습니다. 어떤 아이디어? JPA (eclipselink)에서 캐싱 사용 안 함

나는 다음과 같은 코드를 실행하려고 : 나는 그것이 거짓하려는 동안

 EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("default"); 
     EntityManager em = entityManagerFactory.createEntityManager(); 

     MyLocation one = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0); 

     MyLocation two = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0);  

     System.out.println(one==two); 

하나 == 두 사실이다.

I 각 추가 시도/모든 내의 persistence.xml에 다음

<property name="eclipselink.cache.shared.default" value="false"/> 
<property name="eclipselink.cache.size.default" value="0"/> 
<property name="eclipselink.cache.type.default" value="None"/> 

나는 또한 엔티티 자체에 @Cache 주석을 추가하는 시도 :

@Cache(
    type=CacheType.NONE, // Cache nothing 
    expiry=0, 
    alwaysRefresh=true 
) 

내가 오해하고 있는가 뭔가 ?

+0

제임스를 호출하여 데이터베이스로 이동하기 위해 각각의 쿼리를 강제 할 수, 캐싱은 <속성 이름 = "eclipselink.cache.shared.default (벗어났다 "value ="false "/> ) 테스트했을 때? – Justin

+0

죄송 합니다만, 캐싱이 꺼져 있습니다. 나는 여전히이 문제를 안고 있으며 해결책이 없다. – James

답변

34

이 동작은 정확합니다. 그렇지 않으면 개체 1과 개체 2를 다른 값으로 변경하면 개체를 유지할 때 문제가 발생합니다. 첫 번째 호출에서로드 된 개체가 두 개의 업데이트를로드하는 호출이 발생합니다. 그것들은 같은 대상이므로 같은 대상을 가리켜 야합니다. 이렇게하면 더러운 데이터를 쓸 수 없습니다.

두 번의 호출 사이에서 em.clear()를 호출하면 엔티티 하나가 분리되고 검사에서 false가 반환됩니다. 그러나 그것을 할 필요가 없습니다, 이클립스 링크가 실제로 내가 추측 할 수있는 최신 데이터를 업데이 트하는 것은 그것이 자주 변경되기 때문에 당신이 원하는 것입니다.

JPA를 사용하여이 데이터를 업데이트하려면 엔터티에서 pessimistic locks을 얻어야 기본 데이터가 DB에서 변경 될 수 없습니다. 코드에서

: 새 결과를 얻지 못하고있는 이유

당신은 당신의 캐시 옵션은 단지 재생되지 쿼리 캐시에서 개체 캐시를 제거하고뿐만 아니라 쿼리 캐시를 사용하지 않도록해야합니다, 즉

em.createNamedQuery("MyLocation.findMyLoc").setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache).getResultList().get(0); 

또는이 persistence.xml에 :

<property name="eclipselink.query-results-cache" value="false"/> 
+0

감사합니다. 나는 데이터가 변하기 때문에 비관적 인 자물쇠를 봐야 할 것이다. 어떻게하면 스레드를 추가 할 수 있습니다.절전 (10000) 사이의 쿼리 및 그 시간에 수동으로 데이터베이스에서 MyLocation의 특성을 변경 두 (따라서 하나의)이 변경 반영하지? – James

+0

은 비관적 잠금에 대한 정보에 대한 링크를 추가했습니다 – Justin

+0

코드 및 persistence.xml에서 설명한 변경을 시도했지만 여전히 변경된 값을 얻지 못했습니다. 어떤 아이디어? – James

3

수동 예를 들어 MyLocation를 들어, 객체의 속성을 수정합니다. 위의 트릭 (CACHE_USAGE=CacheUsage.DoNotCheckCache 또는 eclipselink.query-results-cache=false)은 제가 시도한 것처럼 작동하지 않습니다.

그래서 eclipselink.refresh 인 또 다른 힌트를 설정하려고 시도했습니다. true입니다. 그것은 작동합니다. 수동으로 변경된 속성이 검색된다는 의미입니다.

위의 트릭은 올바른 오브젝트를 얻을 수 있음을 이해합니다. 그러나 개체가 이미 캐시 된 경우 eclipselink는 개체 내용의 신선도를 확인하지 않고 개체를 반환합니다. 힌트 eclipselink.refreshtrue으로 설정된 경우에만 최신 특성 값을 반영하여 이러한 개체가 새로 고쳐집니다.

+4

Hava 당신은 당신의 persistence.xml에서 이것을 설정합니까? 이 힌트를 쿼리에 추가하면 작동합니다. 하지만 내 persistence.xml에서만 정의하면 작동하지 않습니다. – Christian

22

이것은 저에게 적합합니다.같은 EntityManager의 JPA를 들어

+0

이 하나 의외로 작동 – kebyang

+0

이것은 나를 위해 일한 하나뿐입니다. –

10

참조,

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching

는 항상 하나 ==이 필요하므로이 올바른지, 캐싱 옵션을 (이 L1 캐시, 또는 트랜잭션 캐시입니다 중요하지 어떤 트랜잭션 격리를 시행하고 객체 ID를 유지 관리합니다.

쿼리를 강제로 새로 고치고 변경 한 내용을 되돌리려면 쿼리 힌트 "eclipselink.refresh"= "true"를 사용할 수 있습니다. 또는 각 쿼리/요청에 대해 새로운 EntityManager를 사용하거나 EntityManager에서 clear()를 호출하는 것이 더 좋습니다.

<property name="eclipselink.cache.shared.default" value="false"/> 

공유 캐시 (L2 캐시)를 비활성화하는 올바른 방법입니다. 다른 모든 설정을 올바르지 않게 제거하십시오. 문제가 발생할 수 있습니다.

EclipseLink는 기본적으로 쿼리 캐시를 유지하지 않으므로 이러한 설정은 아무런 영향을 미치지 않습니다. CacheUsage가 정확하지 않습니다. 메모리 사용량을 쿼리하는 용도로 사용하지 마십시오. 나는이 게시물에 오래된 수 있습니다 알고

@Entity 
@Table(name="SomeEntity") 
@Cacheable(false) 
public class SomeEntity { 
    // ... 
} 
+1

EclipseLink (https://bugs.eclipse.org/bugs/show_bug.cgi?id=398074)의 현재 버전에서는 "eclipselink.refresh"= "true"가 버그입니다. 또한, JPA의 일부가 아닌 EclipseLink 전용입니다. 따라서 신선한 데이터를 원할 때마다 신선한 EntityManager를 얻는 것이 좋습니다. 이것이 JPA와 함께 작동하는 방법입니다. – sleske

+0

새로운 EntityManager를 얻는다고해서 데이터베이스에서 직접 새로운 객체를 얻을 수는 없습니다. 캐시는 일반적으로 응용 프로그램의 수명이있는 EntityManagerFactory 수준에서 작동합니다. – OliBlogger

7

당신은 당신이 당신의 도메인 객체에 주석 수, 공급 업체가 특정받지 않고 캐싱을 사용하지 않도록하려면 하지만 도움이 필요한 사람들을 위해 글을 쓰고 있습니다. 나는이 문제를했고 마지막으로이 코드에 의해 그것을 해결 : 정말 잘 작동

em.createNamedQuery("findAll").setHint(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.BYPASS).getResultList(); 

. 그리고 우리는 javadoc에서 BYPASS enum을 볼 수 있습니다 :

바이 패스 캐시 : 데이터베이스에서 직접 데이터를 가져옵니다.

Weblogic 12c와 TopLink를 JPA 구현으로 사용함에 유의해야합니다.

3

:

여기
@Cacheable(false) 

은 예입니다

+0

위에서 언급 한 새로 고침 힌트가 효과가 없습니다. – cen

+0

일부 쿼리에서 jpa 캐시를 무시하기 때문에 시도하지 않았습니다. – AliReza19330

1

첫 번째 수준의 캐시는 기본적으로 사용되며 사용하지 않도록 설정할 수 없습니다. 즉, persistence.xml 파일의 설정으로는 첫 번째 레벨 캐시가 비활성화되지 않습니다.

만 개체를 ​​다시 캐시에 저장되어 다음이 후속 쿼리 (처음으로) 데이터베이스로 이동하게됩니다

entityManager.clear() 

를 호출하여 모든 엔티티 관리자 객체를 취소 할 수 있습니다

당신은 바로 내 대답에 귀하의 코멘트에

query.setHint("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH);