6
public enum ReportStatus { 
    SUCCCEED, FAILED;
}

public class Work {
    @ElementCollection
    @Enumerated(EnumType.STRING)
    List<ReportStatus> reportStatuses;
}

鉴于以下结构,我想执行查询以查找所有由 reportStatuses 过滤的工作。它适用于以下 hql 语法:

public List<Long> queryHQL() {
    final String query = "SELECT w.id FROM Work w JOIN w.reportStatuses s WHERE s in (:rs)";

    final List<ReportStatus> reportStatuses = new ArrayList<ReportStatus>();
    reportStatuses.add(ReportStatus.FAILED);

    return this.entityManager.createQuery(query).setParameter("rs", reportStatuses).getResultList();
}

但我想使用标准 API (jpa2),但不知道该怎么做。这是我认为的最接近的尝试:

public List<Long> query() {
    final List<ReportStatus> reportStatuses = new ArrayList<ReportStatus>();
    reportStatuses.add(ReportStatus.FAILED);

    final CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

    final CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
    final Root<Work> workModel = criteriaQuery.from(Work.class);

    final ListJoin<Work, ReportStatus> status = workModel.joinList("reportStatuses");

    final Predicate predicate = status.in(reportStatuses);

    criteriaQuery.where(predicate);
    criteriaQuery.select(workModel.<Long> get("id"));

    return this.entityManager.createQuery(criteriaQuery).getResultList();
}

我也尝试过使用休眠标准 API,但作为 jpa2 的 API,我找不到正确的语法。

4

3 回答 3

5

我会使用以下 CriteriaQuery 语法来做同样的事情。

EntityManager em = entityManagerFactory.createEntityManager();

final List<ReportStatus> reportStatuses = new ArrayList<ReportStatus>();
reportStatuses.add(ReportStatus.FAILED);

final CriteriaBuilder builder = em.getCriteriaBuilder();

final CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
final Root<Work> _work = criteriaQuery.from(Work.class);

/*final ListJoin<Work, ReportStatus> status = _work.joinList("reportStatuses");
final Predicate predicate = status.in(reportStatuses);
criteriaQuery.where(predicate);*/

final Expression<List<ReportStatus>> _status = _work.get(Work_.reportStatuses);
_status.in(reportStatuses);

criteriaQuery.select(_work.get(Work_.id));

List<Long> list =  em.createQuery(criteriaQuery).getResultList();

更新

谢谢,但我们不使用生成的元模型。所以不幸的是,我无法尝试您的答案。:(

如果您不使用 Metamodel,只需替换_work.get(Work_.reportStatuses)_work.get("reportStatuses"). 它会工作的。:)

于 2010-12-09T16:47:35.460 回答
3

您可以创建此 HQL。

String query = "SELECT w.id FROM Work w, IN(w.reportStatuses) s WHERE s = :rs";
return this.entityManager.createQuery(query).setParameter("rs", ReportStatus.FAILED).getResultList();
于 2011-08-20T21:12:17.907 回答
1

我很困惑。调用in(..)返回一个谓词,但似乎并没有真正执行它(它似乎没有集成到查询中——至少对我来说,它返回了根的所有成员,无论它们的集合是否与 . 相交reportStatuses。调试日志显示了简单的查询select distinct work0_.id as id18_ from Work work0_)。

此外,如果调用者只对匹配一个值的那些感兴趣,为什么还要将 reportStatuses 放入列表中?您将如何仅使用ReportStatus.FAILED而不是为其构建列表来进行查询?

于 2011-07-05T15:59:33.740 回答