2011-11-27 1 views
3

JPA/Eclipse TopLink 사용. 아래 그림과 같이JPQL createQuery 사용시 이전 데이터 반환

나는 (createNativeQuery 사용) 테이블을 갱신하고 있습니다 :

업데이트는 아래 표와 같이 (createQuery 사용) 검색을 위해

DB를 (MySQL의)에 반영됩니다

Query query = em.createNativeQuery("UPDATE Products SET productName='" + p.getProductName() + "',productVendor='" + p.getProductVendor() + "',productDescription='" + p.getProductDescription() + "',quantityInStock=" + p.getQuantityInStock() + ",buyPrice =" + p.getBuyPrice() + ",msrp=" + p.getMsrp() + " WHERE productCode='" + p.getProductCode() + "'"); 
query.executeUpdate(); 

:

Query query1 = em.createQuery("SELECT p from Products p where p.productCode='"+searchTerm+"'"); 
return query1.getResultList(); 

그러나 반환 된 ResultList는 항상 업데이트 전의 데이터입니다. createQuery 대신 createNativeQuery를 사용하면 최신 업데이트 된 데이터가 반환됩니다. createQuery 메서드로 가능한 오류가 무엇입니까?

답변

6

일괄 업데이트 또는 기본 쿼리를 사용할 때 첫 번째 수준 캐시를 건너 뜁니다. Toplink는 이미 첫 번째 레벨 캐시에있는 엔티티가 변경되었음을 알 수있는 방법이 없습니다. 따라서 엔티티 관리자는 쿼리가 새로 고침 된 객체를 다시 시작하도록 지워야합니다.

하지만 가장 좋은 방법은 처음에는 배치 업데이트를 피하는 것이 가장 좋습니다. 첫 번째 쿼리는 지정된 코드로 제품을로드하는 JPQL 쿼리로 대체 한 다음 단순히 Product 엔터티를 업데이트합니다. 업데이트 쿼리를 유지하더라도 SQL이 아닌 JPQL로 작성할 수 있습니다 (하지만 여전히 문제가있을 수 있습니다).

Query query1 = em.createQuery("SELECT p from Products p where p.productCode = :searchTerm); 
query1.setParameter("searchTerm", searchTerm); 
return query1.getResultList(); 
+1

감사합니다, JB Nizet을 :

마지막으로, 쿼리는 주사를 방지하고 있는지 모든 것이 제대로 이스케이프하기 위해 매개 변수를 사용해야합니다. 좋은 설명입니다. em.clear()를 사용하여 엔터티 관리자 캐시를 지우는 것이 도움이되지 않았습니다. 그래서 나는 캐시를 우회하여 결국 - query.setHint ("javax.persistence.cache.storeMode", "BYPASS"); 그리고 효과가있었습니다. (저는 우회가 캐시의 모든 목적을 저지하고 이전 게시물에서 언급 한 것처럼 배치 업데이트와 기본 쿼리를 사용하지 않을 것임을 이해합니다). 다시 한번 감사드립니다. – srock