JPA:具有限制的多级获取

时间:2016-06-24 20:53:01

标签: hibernate jpa

我正在尝试使用JPA CriteriaQuery通过对数据库的一次调用来获取多个级别的实体。

NamedEntityGraph:

goto

用于获取实体的Load方法:

@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 {
    ...
}

除了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();
}

所以我的问题是,在某种程度上可以在数据库中执行限制吗?

我尝试从子选择中进行选择,但我无法弄清楚如何在JPA中执行以下SQL语句

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

1 个答案:

答案 0 :(得分:1)

我最后使用了对数据库的附加调用,我在其中获取了受排序和过滤器选项限制的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();
}