【问题标题】:Tuple result Criteria API subquery元组结果条件 API 子查询
【发布时间】:2011-07-16 02:46:58
【问题描述】:

我正在尝试在使用 JPA 2.0 类型安全标准 API 编写的应用程序中使用子查询,并使用 Hibernate 3.6.1.Final 作为我的提供者。我选择原始类型(Long、MyEntity 等)没有问题,但我想选择多个列。

这是一个完全合理的例子。忽略子查询的不必要使用——它只是为了说明。

    EntityManager em = getEntityManager();
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Tuple> cq = cb.createTupleQuery();

    Subquery<Tuple> subQ = cq.subquery(Tuple.class);
    Expression<Long> subqCount;
    {
        Root<MyEntity> root = subQ.from(MyEntity.class);
        Path<MyEntity> filter = root.get(MyEntity.challenge);

        subqCount = cb.count(root);

        // How to select tuple?
        Selection<Tuple> tuple = cb.tuple(filter, subqCount);

                    // !! Run-time exception here
        Expression<Tuple> tupleExpr = (Expression<Tuple>) tuple; 

        // Not sure why I can't use multiSelect on a subQuery
        // #select only accepts Expression<Tuple>
        createSubQ.select(tupleExpr);

        createSubQ.groupBy(filter);
    }

    cq.multiselect(subqCount);

虽然编译器没有报错,但我还是遇到了运行时异常。

    java.lang.ClassCastException: org.hibernate.ejb.criteria.expression.CompoundSelectionImpl cannot be cast to javax.persistence.criteria.Expression
  • 这是休眠中的错误,还是我做错了什么?
  • 如果您不能在子查询中使用multiselect,那么如何执行groupBy
  • 如果您不能在子查询中使用groupBy,为什么要在 API 中使用它?

【问题讨论】:

  • 我仍然没有找到这个问题的答案,我认为它仍然有效。

标签: jpa subquery criteria jpa-2.0 criteria-api


【解决方案1】:

我也有同样的问题。

我只能尝试回答您的最后一个问题,即您只能真正使用子查询来执行非常简单的查询,例如:

SELECT name FROM Pets WHERE Pets.ownerID in (
    SELECT ID FROM owners WHERE owners.Country = "SOUTH AFRICA"
)

我想说的另一件事是这件事让我想起了xkcd #979

【讨论】:

  • +1 - 喜欢 XKCD 参考,我同意子查询似乎相当有限。您是否尝试过使用 JPAQL 进行分组子查询?
  • 我没有,我正在处理的示例(我对 JPA 还是很陌生)需要查询的结构根据选择的内容发生很大变化,所以我基本上只是使用了子查询我需要作为我的主要查询,然后“手动”过滤掉其他所有内容。无论如何,查询只会返回少于几千个元组,所以它不会太慢。
【解决方案2】:

我有类似的问题。 我有规范,我想获取符合该规范的对象的 ID。

我的解决方案:

    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaQuery<Tuple> tupleCriteriaQuery = criteriaBuilder.createTupleQuery();

    Root<Issue> root = tupleCriteriaQuery.from(Issue.class);
    tupleCriteriaQuery = tupleCriteriaQuery.multiselect(root.get(IssueTable.COLUMN_ID));//select did not work.
    tupleCriteriaQuery = tupleCriteriaQuery.where(issueFilter.toPredicate(root, tupleCriteriaQuery, criteriaBuilder));

    List<Tuple> tupleResult = em.createQuery(tupleCriteriaQuery).getResultList();

首先我选择列(在我的例子中我只需要一列),然后我调用 where 方法来合并我给定的规范。

【讨论】:

    猜你喜欢
    • 2014-10-29
    • 2015-04-24
    • 2011-02-18
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多