我正在尝试使用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!
答案 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();
}