2012-04-18 5 views
2

저는 JPA 2.0을 처음 접했고 이해할 수없는 몇 가지 사항이 있습니다.JPQL 쿼리 : 관계에있는 행을 필터링하는 방법?



    CUST table (for customers) 
    -------------------------- 
    CUST_ID (pk, integer) 
    CUST_NAME (varchar) 



    ORD table (for orders) 
    ---------------------- 
    ORD_ID  (pk, integer) 
    ORD_STATUS (char) can be: 'N' for new, 'S' for shipped, 'D' for delivered 
    CUST_ID (fk, integer) 

의 관계는 "많은 한"간단 (모든 고객이 많은 주문을 배치 할 수 있습니다) :

나는 테이블의 몇 가지있다. 테이블의

콘텐츠 :



    @Entity(name = "Customer") 
    @Table(name = "CUST") 
    public class Customer implements Serializable 
    { 
     private static final long serialVersionUID = 1L; 

     @Id 
     @Column(name = "CUST_ID") 
     private Integer id; 

     @Column(name = "CUST_NAME") 
     private String name; 

     @OneToMany(mappedBy = "customer") 
     private List<Order> orders; 

     // Default constructor, getters and setters (no annotations on these) 
    } 



    @Entity(name = "Order") 
    @Table(name = "ORD") 
    public class Order implements Serializable 
    { 
     private static final long serialVersionUID = 1L; 

     @Id 
     @Column(name = "ORD_ID") 
     private Integer id; 

     @Column(name = "ORD_STATUS") 
     private Character status; 

     @ManyToOne 
     @JoinColumns 
     (
      { 
      @JoinColumn(name = "CUST_ID", referencedColumnName = "CUST_ID") 
      } 
     ) 
     private Customer customer; 

     // Default constructor, getters and setters (no annotations on these) 
    } 

0,123,516 :



    CUST_ID | CUST_NAME 
    ------------------- 
    1  | elcaro 
    2  | tfosorcim 
    3  | elppa 



    ORD_ID | ORD_STATUS | CUST_ID 
    ----------------------------- 
    2  | N   | 1 
    3  | N   | 1 
    4  | N   | 1 
    5  | S   | 1 
    6  | S   | 1 
    7  | D   | 1 
    8  | D   | 1 
    9  | D   | 1 
    10 | D   | 2 
    11 | N   | 2 
    12 | S   | 3 
    13 | S   | 3 

여기에 내가 내 수업을 주석 방법

`select c from Customer c`

이 유형의 고객의 세 가지 객체를 반환하는 각각의 해당 고객에 속한 주문을 포함

모든 다음 JPQL 쿼리는 내가 기대했던 결과를 얻을 수, 잘 작동합니다.

하지만 지금은 관련 주문 (상태 'N'주문 만)과 함께 상태 'N'의 주문이있는 고객 목록을 추출하려고합니다. 위로 좋은 똑똑한에서 '일이 같은 SQL 쿼리를 작성했을 :



    select  c.cust_id, 
       c.cust_name, 
       o.ord_id, 
       o.ord_status 
    from  cust c 
    inner join ord o on (o.cust_id = c.cust_id) 
    where  o.ord_status = 'N' 

그것은 다음과 같은 결과 집합을 반환 것입니다 :



    CUST_ID | CUST_NAME | ORD_ID | ORD_STATUS 
    ----------------------------------------- 
    1  | elcaro | 2  | N 
    1  | elcaro | 3  | N 
    1  | elcaro | 4  | N 
    2  | tfosorcim | 11  | N 

하는 JPQL 쿼리 다음, 그러나, 아무튼를 'T는 예상 된 결과를 얻을 :

`select distinct c from Customer c join c.orders o where o.status = 'N'`

는 고객의 정확한 세트 (고객 반환'elppa N '순서와 정확히 제외'어떤 상태가 없습니다 ')를하지만, 각 고객은 상태에 관계없이 모든 주문 세트를 포함합니다. 'where'절은 추출해야하는 고객 집합을 결정하기 위해 평가 된 다음 지속성 공급자가 전체 주문 집합을 추출하기 위해 관계를 탐색하기 시작한 것처럼 보입니다. 그것에 대해 조금 생각하면 의미가 있다는 것을 인정해야합니다. 각 결과 (예상대로 4 개 결과) 2 개체입니다 : 이전 SQL 쿼리에 의해 생성 된 것과 유사하다

`select c, o from Customer c join c.orders o where o.status = 'N'`

이 JPQL 쿼리 수익률 결과 :

나는 다음 다른 JPQL 쿼리를 시도 배열에서 첫 번째 객체는 Customer 유형이고 두 번째 객체는 Order 유형입니다. 그러나 다시 Customer 유형의 객체에는 관련 주문 전체가 포함됩니다 (이번에는 예상 한대로). 이제 주문은 Customer 객체에 포함되지 않지만 SQL 결과 집합과 마찬가지로 별도로 반환된다는 사실은 말할 필요도 없습니다.

이제 질문은 다음과 같습니다. 상태 'N'의 주문이없는 고객뿐만 아니라 관계 탐색 중에 페치 된 관련 주문을 걸러내는 JPQL 쿼리를 작성할 수 있습니까? 상태 'N'에도 없습니까? 내가 얻을 수 있기를 원하는 것은 각 고객이 상태 'N'주문 만 포함하는 2 고객 결과입니다.

자바 EE 6 자습서를 읽었으며 예제 중 하나 (주문 애플리케이션)에 비슷한 스키마가 있지만 다운로드 한 소스 코드에서 이와 같은 쿼리를 찾을 수 없습니다.

위의 내용이 표준 동작이라고 생각하지만 Oracle Weblogic 12c 서버 (Eclipse 어댑터를 통해)를 사용하고 지속성 공급자는 EclipseLink 인 것으로 나타났습니다.

미리 감사드립니다.

안부,

스테파노

답변

3

JPA 개체와 거래, 그리고 객체가 정체성을 가지고 상관없이이 조회하는 방법을 동일합니다. where 절이 무엇이든간에 리턴 된 Customer 오브젝트는 여전히 동일한 Customer 오브젝트이며 동일한 관계를 가져야합니다. 이는 캐싱, 객체 동일성 및 일관성에 중요합니다.

두 번째 쿼리는 아마도 원하는 작업을 수행하는 올바른 방법 일 것입니다. JOIN FETCH (EclipseLink 2.4 현재)에서 별명을 사용하여 수행하려는 작업을 수행 할 수 있지만 권장하지는 않습니다.

참조, http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#JOIN_FETCH

+0

안녕하세요 제임스, 회신 주셔서 감사합니다. 나는 join fetch를 사용하는 것이 스트레치 (그리고 그것은 또한 운율이 붙는다)라는 것에 동의한다. 주문에 대해 직접 질문하고 고객에 대한 참조를 활용하도록 제안되었습니다. 사실 다음 쿼리로 올바른 결과를 얻을 수있었습니다 : o를 o.status = 'N'으로 선택하여 o를 선택합니다. 선택한 주문 만 들어있는 각 고객의 사본 한 장을 갖고 싶지만이 솔루션에도 만족합니다. 고마워, 안녕. – Stefanuzzo

관련 문제