2016-11-18 16 views
3

私のプロジェクトでは、SpringデータJPAのSpecificationでGroovyを使用して、Hibernateクエリを構築しています。JPA基準では、結合エンティティの子エンティティをフェッチする方法は?

私は実際のクエリを提供することはできませんが、私の問題を説明するために、建物のエンティティがあり、各建物に階があり、各階に部屋と窓があるとします。

私がシミュレートしようとしてるの行動は、このネイティブSQLクエリのようなものです:

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; 

私は以下に似た仕様を持っている:

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); 
    } 
} 

上記の注釈付きの行は私の問題です。私はそれを取り外してから、部屋をフェッチする代わりに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.*データを気付か)

:私はそれを残す場合は、生成されたクエリは次のようになります私はトンと上記floorsJoinを置き換えることはできません以外

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

不要なf2.*データはOK、次のようになります、私は次のHibernateのエラーを取得します彼はwindowsテーブル(windowsを取得せず)に参加する必要があり、Fetchクラスは.joinメソッドを持たないので、私はfloorsFetchです。

私は、1つのクエリを生成しながら必要なものをどのように達成するかを考え出すのが難しいです。確かに私は何か簡単なものを欠いているに違いない。

ご提供いただけるご意見やアドバイスをいただければ幸いです。

どうもありがとう、 B.J.

答えて

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 
); 
関連する問題