Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jpa 如何计算子查询返回的行数?_Jpa_Jpa 2.0_Jpql_Criteria Api - Fatal编程技术网

Jpa 如何计算子查询返回的行数?

Jpa 如何计算子查询返回的行数?,jpa,jpa-2.0,jpql,criteria-api,Jpa,Jpa 2.0,Jpql,Criteria Api,我想这样做: select count(*) from (select ...) 就像在SQL中一样,但是在JPA中 有什么想法吗?如果您想使用JPA标准API,这应该可以做到: CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); CriteriaQuery<Long> query = cb.createQuery(Long.class); Root<Entity> root = query.

我想这样做:

select count(*) from (select ...)
就像在SQL中一样,但是在JPA中


有什么想法吗?

如果您想使用JPA标准API,这应该可以做到:

CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();  
CriteriaQuery<Long> query = cb.createQuery(Long.class);

Root<Entity> root = query.from(Entity.class);

//Selecting the count
query.select(cb.count(root));

//Create your search criteria
Criteria criteria = ...

//Adding search criteria   
query.where(criteria);

Long count = getEntityManager().createQuery(query).getSingleResult();

我也偶然发现了这个问题。我最终希望执行以下JPQL:

选择COUNTu 从…起 选择不同的u 来自用户u 加入u.r 其中r.id在1中 但这是不可能的,也不符合API标准。研究表明,这只是JPA中的一个设计限制。JPA规范规定,子查询仅在WHERE和HAVING子句中受支持,因此在FROM中不受支持

以以下JPQL格式重写查询:

选择COUNTu 来自用户u 你在哪里 选择不同的u 来自用户u 加入u.r 其中r.id在1中 使用JPA标准API,如下所示:

CriteriaQuery=cb.createQueryLong.class; Root u=query.fromUser.class; Subquery Subquery=query.subqueryUser.class; Root u_u2;=subquery.fromUser.class; subquery.selectu_u.distincttrue.whereu_u.joinroles.getid.inArrays.asList1L; query.selectcb.countu.wherecb.inu.valuesubquery; 长计数=entityManager.createQueryquery.getSingleResult; // ...
为我解决了功能需求。这也将使您能够充分了解如何解决特定的功能需求。

使用以下代码段来计算给定条件查询的行数:

public static Query createNativeCountQuery(EntityManager em, CriteriaQuery<?> criteriaQuery) {
  org.hibernate.query.Query<?> hibernateQuery = em.createQuery(criteriaQuery).unwrap(org.hibernate.query.Query.class);
  String hqlQuery = hibernateQuery.getQueryString();

  QueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
  QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator(
    hqlQuery,
    hqlQuery,
    Collections.emptyMap(),
    em.getEntityManagerFactory().unwrap(SessionFactoryImplementor.class),
    null
  );
  queryTranslator.compile(Collections.emptyMap(), false);

  String sqlCountQueryTemplate = "select count(*) from (%s)";
  String sqlCountQuery = String.format(sqlCountQueryTemplate, queryTranslator.getSQLString());

  Query nativeCountQuery = em.createNativeQuery(sqlCountQuery);

  Map<Integer, Object> positionalParamBindings = getPositionalParamBindingsFromNamedParams(hibernateQuery);
  positionalParamBindings.forEach(nativeCountQuery::setParameter);

  return nativeCountQuery;
}

private static Map<Integer, Object> getPositionalParamBindingsFromNamedParams(org.hibernate.query.Query<?> hibernateQuery) {
  Map<Integer, Object> bindings = new HashMap<>();

  for (var namedParam : hibernateQuery.getParameterMetadata().getNamedParameters()) {
    for (int location : namedParam.getSourceLocations()) {
      bindings.put(location + 1, hibernateQuery.getParameterValue(namedParam.getName()));
    }
  }

  return bindings;
}

问题是我想要得到子查询返回行的计数。这似乎是不可能的,因为子查询不能像在JPAThis中那样使用,它根本不能回答具体的问题。OP询问的是如何计算子查询的结果,而不是如何计算查询的结果。如果返回的行数为零,则此操作不起作用。Hibernate使用javax.persistence.NoresultException进行崩溃如果您想计算聚合的结果,就不能使用这种方法query@Martin你建议用什么方法来区分计数和任意标准查询?@svlada,我没有找到有效的解决方案,只返回所有行并在应用程序服务器上对它们进行计数。@Martin在这种情况下,我认为唯一的选择是执行普通的JDBC查询。除了枚举和列表参数外,它还可以工作
public static Query createNativeCountQuery(EntityManager em, CriteriaQuery<?> criteriaQuery) {
  org.hibernate.query.Query<?> hibernateQuery = em.createQuery(criteriaQuery).unwrap(org.hibernate.query.Query.class);
  String hqlQuery = hibernateQuery.getQueryString();

  QueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
  QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator(
    hqlQuery,
    hqlQuery,
    Collections.emptyMap(),
    em.getEntityManagerFactory().unwrap(SessionFactoryImplementor.class),
    null
  );
  queryTranslator.compile(Collections.emptyMap(), false);

  String sqlCountQueryTemplate = "select count(*) from (%s)";
  String sqlCountQuery = String.format(sqlCountQueryTemplate, queryTranslator.getSQLString());

  Query nativeCountQuery = em.createNativeQuery(sqlCountQuery);

  Map<Integer, Object> positionalParamBindings = getPositionalParamBindingsFromNamedParams(hibernateQuery);
  positionalParamBindings.forEach(nativeCountQuery::setParameter);

  return nativeCountQuery;
}

private static Map<Integer, Object> getPositionalParamBindingsFromNamedParams(org.hibernate.query.Query<?> hibernateQuery) {
  Map<Integer, Object> bindings = new HashMap<>();

  for (var namedParam : hibernateQuery.getParameterMetadata().getNamedParameters()) {
    for (int location : namedParam.getSourceLocations()) {
      bindings.put(location + 1, hibernateQuery.getParameterValue(namedParam.getName()));
    }
  }

  return bindings;
}