2016-11-18 4 views
3

내 프로젝트에서 Spring 데이터 JPA의 Specification으로 Groovy를 사용하여 최대 절전 모드 쿼리를 구성했다.JPA 기준을 사용하면 결합 된 엔터티를 가져 오지 않고 결합 된 엔터티의 하위 엔터티를 가져 오는 방법은 무엇입니까?

저는 실제 쿼리를 제공 할 수 없지만 건물에 엔티티가 있으며 각 건물에 층이 있고 각 층에 룸과 Windows가 있다고 가정 해 보겠습니다.

내가 시뮬레이션을 시도하고있어 동작이 기본 SQL 쿼리 같은 것입니다 :

위의 주석 라인은 내 문제
public class MySpec implements Specification<Building> { 
    @Override 
    public Predicate toPredicate(final Root<Building> root, final CriteriaQuery<?> query, final CriteriaBuilder cb) { 
     final Join floorsJoin = root.join("floors"); 
     final Join windowsJoin = floorsJoin.join("windows"); 

     //I'd like to remove this line 
     final Fetch floorsFetch = root.fetch("floors"); // <--- 

     floorsFetch.fetch("rooms", JoinType.LEFT); 

     cb.equal(windowsJoin.get("id"), 1L); 
    } 
} 

이다 : 나는 다음과 같은 사양을 가지고

SELECT b.*, r.* 
FROM building b 
INNER JOIN floor f ON b.id = f.building_id 
INNER JOIN window w ON f.id = w.floor_id 
LEFT OUTER JOIN room r ON f.id = r.floor_id 
WHERE w.id = 1; 

. 내가 떠날 경우, 생성 된 쿼리는 다음과 같은 : 내가 그것을 제거하고 객실을 가져 오는 대신 floorsJoin를 사용하는 경우

SELECT b.*, f2.*, r.* 
FROM building b 
INNER JOIN floor f ON b.id = f.building_id 
INNER JOIN window w ON f.id = w.floor_id 
INNER JOIN floor f2 ON b.id = f2.building_id 
LEFT OUTER JOIN room r ON f2.id = r.floor_id 
WHERE w.id = 1; 

(floor의 중복 INNER JOIN과 불필요한 f2.* 데이터를 통지) 나는 t으로 위의 floorsJoin을 대체 할 수 없습니다 제외

org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list 

불필요한 f2.* 데이터가 확인 될 것이다 : 나는 다음 최대 절전 모드 오류 그는 windows 테이블 (windows을 가져 오지 않고)에 참여해야하고 Fetch 클래스에는 .join 메소드가 없기 때문에 그는 floorsFetch입니다.

나는 하나의 쿼리를 생성하면서 필요한 것을 어떻게 달성 할 수 있는지 알아 내려고 어렵습니다. 틀림없이 나는 간단한 것을 놓치고 있어야합니다.

당신이 제공 할 수있는 생각이나 충고는 크게 감사하겠습니다.

고마워, 비제이

답변

0

글쎄 그것은 JPA 기준 API와 간단하지 않습니다. Hibernate를 사용하면 FetchJoin으로 간단하게 캐스팅 할 수 있습니다.하지만 그렇게 많이 도움이되지는 않을 것입니다. 이 경우 사양을 어떻게 사용하는지 잘 모르겠지만 쿼리를 전체적으로 작성할 수 있다면 다음과 같이 보일 수 있습니다.

CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Tuple> cq = cb.createTupleQuery(); 

Root<Building> root = cq.from(Building.class); 
final Join floorsJoin = root.join("floors"); 
final Join windowsJoin = floorsJoin.join("windows"); 
final Join roomsJoin = floorsJoin.join("rooms", JoinType.LEFT); 

cb.equal(windowsJoin.get("id"), 1L); 

cq.multiselect(
    root, 
    roomsJoin 
);