2014-02-12 5 views
4

내 프로젝트에는 JPA 계층 Location -> Site이 있습니다.계층 구조에서 검색된 엔티티 클래스

@Entity 
@Table(name = "LOCATION") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="LOC_TYPE",discriminatorType=DiscriminatorType.STRING) 
public class Location { 
    ... 
} 

@Entity 
@DiscriminatorValue("SI") 
public class Site extends Location { 
    ... 
} 

이제 모든 Employee는 (지금까지 내가 말할 수있는, 그러한 모든 위치가 실제로 Site 경우에도) 할당 Location의 목록이 있습니다. 어떤 부분에서는 Employee에 할당 된 Site의 목록이 필요합니다 (참고로, 내가 정의한 관계는 Location입니다).

Hibernate 3.2에서 나는 Location에 대한 쿼리를 작성하고 discriminant에 의해 필터링 할 수 있습니다. 반환 된 클래스는

Query query = em.createQuery("SELECT loc FROM Location loc WHERE loc.type=\"SI\""); 
List<Location> locations = (List<Location>) query.getResultList(); 
for (Location location : locations) { 
    Site mySite = (Site) location; 
    ... 
} 

는 그러나, 나는이 문제가 JPA 스펙에 의해 보장되는 경우 알려줍니다 또는 최대 절전 모드에서 바로 구현 결정에 어떤 문서를 찾을 실패 v.g : 더 구체적인 서브 클래스의 인스턴스입니다. 마지막으로 공급자를 전환하면 변경 될 수 있으므로이 방법을 사용하면 안됩니다.

내 접근 방식이 표준에 의해 지원되는지 알려 줄 수 있습니까?

BTW, 내가

UPDATE 최대 절전 모드 3.2 JPA 1을 사용하고 있습니다 : 오든에서

내가 원하는 것을 명확히하기 위해, 이것은 내가 구현 한 "안전 경보"입니다. disc 속성은 discriminator 열이므로 개체가 Site 인스턴스로 유지 된 위치에서 반환 된 것입니다.

Query query = em.createQuery("SELECT lo FROM Employee em JOIN em.location lo WHERE lo.disc = 'SI'"); 
List<Location> locations = (List<Location>) query.getResultList(); 
List<Site> site = new ArrayList<Site>(); 
for (Location location : locations) { 
    if (location instanceof Site) { 
    sites.add((Site) location); 
    } else { 
    log.warn("Found a Location that is not instance of Site"); 
    } 
} 

는 JPA 스펙은 내 log.warn 문이 호출되지 않을 것이라는 점을 지정할 수 있습니까? AFAIK, Site 인스턴스가 아닌 Location을 반환 할 수 있습니다. 물론이 경우 Location 속성 만 사용할 수 있습니다. 이 동작은 C++에서 슬라이싱과 다소 비슷합니다.

+0

아직 문제를 설명하지 않았다고 생각합니다. 'LOC_TYPE' DB 열에 매핑되는 Java 필드'disc'가 있습니까? 그렇지 않다면, 당신은 단순히 그것을 시도 할 수 있습니다. 또한 예제에서 : 단순히 사이트 엔티티를 직접 확인하지 않아도됩니다. 'SELECT s FROM Site s WHERE ...'? –

+0

내 JPQL은 약간의 단순화 였지만 이제는 더 대표적인 것입니다. 'Site' 엔티티는 'Location' 수퍼 클래스 탐색을 통해 얻을 수 있기 때문에 선택할 수 없습니다. 마지막 해결책으로'Location'의 ID를'Site's의 선택으로 되돌려주는 subselect로 해결할 수있었습니다. 그러나이 문제는 나에게 궁금증을 남겼습니다. (또한 나는' IN'는 성능 문제에 대해 하위 선택). – SJuan76

+0

1. Subselect는'IN'보다 나쁩니다. 2. 당신이 1000 개의 값을 가지고 있지 않는 한,'IN'은 결코 문제가되지 않습니다. 3. 당신은 나의 첫 번째 아이디어에 대해 아무 말도하지 않았다. (아마도 이미 그것을 사용했을 것이다.) 당신의'LOC_TYPE' DB 판별 자 칼럼에 매핑되는 자바 필드 eType을 추가하고 당신의 쿼리에 그것을 사용하기 만하면된다. –

답변

5

JPA 버전 2.0부터는 TYPE(e) 기능이 있습니다. 사양에서 예 : JPA 2.0 스펙 (4.6.17.4 엔티티 유형 표현)에서

SELECT e FROM Employee e WHERE TYPE(e) IN (Exempt, Contractor) 

발췌 :

엔티티 타입 표현식 질의 다형성을 제한 할 수 있습니다. TYPE 연산자는 인수의 정확한 유형을 반환합니다.


참고 JPA. 또 다른 측면에서, 예제는 기본 JPA 메커니즘에 의문을 던지며 다시 강조하려고합니다. JPA 쿼리를 사용하여 DB에서 Site 엔티티에 해당하는 판별 자 값을 사용하여 행을 페치하면 Java 객체는 해당 클래스의 인스턴스가됩니다 (즉, Site 클래스). 이제 사양으로 인해 공급자의 클래스가 Site (즉 fetchedEntity.getClass()==Site.class) 인 것은 아니지만 fetchedEntity instanceof Site이 true를 반환하는지 100 % 확신 할 수 있습니다.


참고 최대 절전 모드. Hibernate에 대한 나의 경험에서 나는 그저 fetchedEntity.getClass() == Site.class이 Hibernate에서 true를 반환한다고 덧붙일 수있다. (사실 fetchedEntity instanceof Site 옆에 있음).

+0

팁 주셔서 감사합니다,이 옵션을 알고있는 것이 좋습니다. 어쨌든, 나는 WHERE 절이 이미 discriminator에 의해 필터링 되었기 때문에 이미 다루어졌다. 검색된'e'가 실제로'Exempt' 나'Contractor' 인스턴스로 생성되었다는 확신이 필요하다. 'Employee') – SJuan76

+0

"섹션은 이미 적용 되었습니까?" 내가 알기에 이것은 JPA 1.0에서 지원되는 경우 정확히 필요하다. 직원은 정확히 '종업원'이 아닌 '면제'또는 '계약자'와 같은 Java 유형이 될 것이다. –

+0

JPA 1은'TYPE'을 지원하지 않습니다 (방금 체크했습니다). 나는 discriminator에 의해 필터링함으로써 해결한다 (나의'JPQL' 에서처럼). 어쨌든 내가 원하는 것은 당신의 마지막 확인을 보장하는 명세의 일부이다. 약간 불안해 할 수도 있지만, 문서에 명시되지 않은 경우 일부 구현에서는 원래 하위 클래스가 아닌 일반 'Employee'엔티티를 반환 할 수 있다고 생각합니다 (이후 'JPQL'요청). – SJuan76

관련 문제