2016-06-24 11 views
0

データベースへの1回の呼び出しを使用して、JPA CriteriaQueryを使用して複数のレベルでエンティティをフェッチしようとしています。JPA:制限付きマルチレベルフェッチ

NamedEntityGraph:

@Entity 
@Table(name = "matchh") 
@NamedEntityGraph(name = "Match.MatchPlayerAssociation.Player", 
    attributeNodes = @NamedAttributeNode(value = "matchPlayerAssociation", subgraph = "player"), 
    subgraphs = @NamedSubgraph(name = "player", type = Player.class, attributeNodes = @NamedAttributeNode("player"))) 
public class Match implements Serializable { 
    ... 
} 

Loadメソッドエンティティをフェッチする:そのHibernateは、一度にすべての行を選択し、メモリ内の結果の制限を行う以外

public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters, String graph) { 
    EntityGraph entityGraph = entityManager.getEntityGraph(graph); 
    CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
    CriteriaQuery<T> query = builder.createQuery(tClass); 
    Root<T> root = query.from(tClass); 
    query.select(root); 

    applyFilters(builder, query, root, filters); 
    applySorting(builder, query, root, sortField, sortOrder); 

    return entityManager.createQuery(query) 
      .setFirstResult(first) 
      .setMaxResults(pageSize) 
      .setHint(QueryHints.HINT_LOADGRAPH, entityGraph) 
      .getResultList(); 
} 

それが正常に動作します。

org.hibernate.hql.internal.ast.QueryTranslatorImpl.list HHH000104: firstResult/maxResults specified with collection fetch; applying in memory! 

私の質問は、どういうわけかデータベースで制限を実行できますか?私はリストを取得し、データベースに追加の呼び出しを使用して終了

は、私が副選択から選択することを試みたが、私はJPA

select m.*, mp.*, p.* from (select id from matchh limit 5,10) m 
     left outer join match_player mp on m.id=mp.matchid 
     left outer join Player p on mp.playerid=p.id; 

答えて

0

で次のSQL文を実行する方法を見つけ出すことはできませんソートとフィルタのオプションによって制限され、実際のクエリを制限するためにこのリストを使用するmatch.id。

public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters, String graph) { 
    EntityGraph entityGraph = entityManager.getEntityGraph(graph); 

    CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
    CriteriaQuery<T> query = builder.createQuery(tClass); 
    Root<T> root = query.from(tClass); 

    query.select(root) 
      .where(root.get("id").in(fetchLimitedListOfIds(builder, first, pageSize, sortField, sortOrder, filters))); 

    applySorting(builder, query, root, sortField, sortOrder); 

    return entityManager.createQuery(query) 
      .setMaxResults(pageSize) 
      .setHint(QueryHints.HINT_LOADGRAPH, entityGraph) 
      .getResultList(); 
} 

private List<ID> fetchLimitedListOfIds(CriteriaBuilder builder, int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) { 
    CriteriaQuery<T> query = builder.createQuery(tClass); 
    Root<T> root = query.from(tClass); 
    query.select(root.get("id")); 

    applyFilters(builder, query, root, filters); 
    applySorting(builder, query, root, sortField, sortOrder); 

    return (List<ID>) entityManager.createQuery(query) 
      .setFirstResult(first) 
      .setMaxResults(pageSize) 
      .getResultList(); 
}