2016-10-06 8 views
0

첫째, 미심쩍어합니다. 명백한 질문이 있거나 질문 인 경우 근본적으로 바보입니다.JPA는 한 번만 쿼리를 생성합니다.

더 많은 학문적 질문은 EntityManager에 걸쳐 있거나 독립적 인 JPA 쿼리 (이름이 뭐든간에)를 만들 수 있는지 알아야합니다. 기본적으로 번은 항상 한 번만 실행하십시오. 나는 Enitity manager 객체의 createXXXQuery 메쏘드에서만 Query 인스턴스를 얻을 수 있다는 것을 이해합니다. 그러나 여전히 다른 방법이 있습니까?

이가 시도하고있는 것이다,

public class MyRepo { 
@PersistenceContext 
private EntityManager em; 

private Query aQueryIntentedtoBePreparedOnlyOnce; 

@PostConstruct 
public void prepareMyQuery(){ 
    aQueryIntentedtoBePreparedOnlyOnce = em.createQuery("...."); // Query with positional params 
    } 

    public void executeMyQuery(){ 
    aQueryIntentedtoBePreparedOnlyOnce.getResultList(); 
    } 
} 

이 완벽하게 처음 실행합니다. 그러나 두 번째로 "Entity Manager Closed"라고 말합니다. EM이 거래 범위가 원인이라고 생각합니다.

이 EM은 컨테이너 관리 (JTA - Spring)이므로 트랜잭션간에 확장 할 수 없습니다. 그리고 Session Bean을 사용하는 것은 옵션이 아닙니다. 그래서이 쿼리를 한 번만 생성하는 방법이 있습니까?

추신 : 여기에 명명 된 쿼리와 쿼리 캐싱은 어디에서 오는가? 명명 된 쿼리를 사용하면 매번 createNamedQuery을 수행하는 것처럼 보입니다. 그리고 쿼리 캐시 계획은 무엇입니까 거기에 좋은 워드 프로세서 무엇입니까?

다른 질문 중 하나는 EM 또는 연결 (JDBC)에서만 쿼리가 작성되는 이유는 무엇입니까? 쿼리를 준비하기 위해 어느 DB를 사용해야하는지 알 필요가 없습니까? 적절한 연결없이 하나를 실행할 수 없도록하는 것이 무엇입니까?

+1

수 없습니다. 평범한 최대 절전 모드로 당신은'DetachedCriteria'를 사용할 수 있습니다 만, 결국은 실행을위한'Criteria' 인스턴스가되어야하고'Session' (JPA 용어로는'EntityManager')이 필요합니다. 그런데 왜 이걸하고 싶니? 어떤/많은 성능 (더 많은 메모리 만 사용함)을 얻지 못할 것이고 실제 쿼리는 JDBC 드라이버에 의해 캐싱됩니다 (구성된 경우). –

+0

@M. Deinum 나는 이것을하지 않아도된다. 내가 뭔가를 놓치고 있는지 궁금하다. 왜 더 많은 메모리를 소비합니까? 쿼리가 내 repo 객체의 멤버이기 때문에? SQL을 매개 변수로 변경하지 않고 JDBC 드라이브가 캐쉬 된 SQL을 사용합니까? – anchreg

+0

아니요.'PreparedStatement'는 바운드 매개 변수가있는 쿼리가 아니라 캐시되기 때문에. 메모리에 더 많은 객체가 있으므로 더 많은 메모리가 있습니다. 이제 매우 짧은 수명의 물체가 생겨서 메모리에서 꽤 빨리 제거됩니다. –

답변

2

각 Query 개체는 특정 EntityManager에 연결되어 있으며 각 EntityManager가 하나의 JDBC 연결에 연결되어있는 것처럼 다른 EntityManager에 재사용 할 수 없습니다.

명명 된 쿼리는 컴파일 된 쿼리와 그에 대한 유용한 메타 데이터를 캐시하는 방법입니다. 일반적으로 em.createQuery을 사용할 때마다 매번 구문 분석합니다. 같은 쿼리를 다시 만날 가능성이 높기 때문에 캐시에 대한 정보를 캐시에 보관할 수도 있지만 필수는 아닙니다.

쿼리는, (a Statement 복귀)을 prepareStatementcreateStatement를 호출 JDBC 연결에 (이전 두 상속 CallableStatement 복귀) 또는 prepareCall (a 이전 상속 PreparedStatement 복귀)에 의해 생성된다. 이 Statement 객체에는 다른 연결로 전환 할 수있는 인터페이스가 없습니다. 드라이버에 따라 Java 응용 프로그램이나 서버에 캐시 될 수 있습니다. Statement는 동일한 연결에서 원하는만큼 여러 번 재사용 할 수 있지만 다른 연결에서는 사용할 수 없습니다.

+0

좋습니다. 감사. 그래서 JPQL 컴파일을 막을 수는 없지만 명명 된 쿼리를 사용하여 성능을 얻을 수 있습니까? – anchreg

+0

하프 예. 명명 된 쿼리는 성능을 약간 향상 시키지만 크게는 향상시키지 않습니다. JPA 제공자는 컴파일 된 패키지를 저장합니다. 이름으로 이름을 만들어야합니다. 일반적으로 주석. – coladict