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();
}
我也尝试过使用hibernate条件API,但作为jpa2,我找不到正确的语法。
答案 0 :(得分: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")
即可。它会起作用。 :)
答案 1 :(得分: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();
答案 2 :(得分:1)
我很困惑。对in(..)
的调用返回一个谓词,但似乎并没有实际执行它(它似乎没有被集成到查询中 - 至少对我来说它返回了根的所有成员,无论它们的集合是否相交使用reportStatuses
。调试日志显示简单查询select distinct work0_.id as id18_ from Work work0_
)。
另外,如果调用者只对匹配一个值的那些人感兴趣,为什么还要将reportStatuses放在列表中呢?如何使用ReportStatus.FAILED
而不是为它构建列表来进行查询?