0

我在使用 JPA CriteriaQuery 进行复合选择时遇到问题。我有三个表 X->Y->Z ,每个 XI 有一个或多个 Y ,每个 YI 有一个或多个 Z 。我有一个 X 对象,我试图为一个 X 选择所有出现的 Z 。

我正在使用的代码:

  CriteriaBuilder cb = em.getCriteriaBuilder();
  CriteriaQuery<Z> criteriaQuery = cb
          .createQuery(Z.class);      
  Root<Z> fromZ = criteriaQuery.from(Z.class);

  X xObj = new X(xObjId);

  Subquery<Y> subquery = criteriaQuery.subquery(Y.class);
  Root<Y> fromY = subquery.from(Y.class);
  subquery.select(fromY.<Y> get("Yid")).distinct(true)
          .where(cb.equal(fromY.get("Xid"), xObj));

  criteriaQuery
          .select(fromZ)
          .where(cb.and(
                  cb.in(from.get("Yid")).value(subquery),
                  cb.and(cb.equal(from.get("Zcolumn1"), 0),
                          cb.equal(from.get("Zcolumn2"), 1))))
          .orderBy(cb.asc(from.get("Zcolumn3")));

  TypedQuery<Z> typedQuery = em.createQuery(criteriaQuery);
  List<Z> results = typedQuery.getResultList();

Xid 和 Yid 是它们各自 Y 和 Z bean 中的外键。

此代码在执行点生成错误,因为我有无效的 SQL:

SELECT t0.Zcolumn1, t0.Zcolumn2, t0.Zcolumn3, FROM Z t0 WHERE (t0.Yid IN (SELECT t1.Yid.t1.Yid FROM Y t1 WHERE (t1.Xid = ?)) AND ((t0.Zcolumn1 = ?) AND (t0.Zcolumn2 = ?))) 按 t0.Zcolumn3 ASC 排序

我不明白为什么子查询会生成 Yid 两次,并且不知道如何修复它,根据我找到并改编的示例,我认为这应该可行。这是我第一次使用 SubQuery,所以请原谅我的代码风格可能出现的愚蠢错误 :)

谢谢你。

4

1 回答 1

0

我不确定你为什么要使用 subQuery 。

这种更简单的方法将为您提供链接到给定 X 实例的 Z 的所有发生。我稍微更改了字段命名:分别是 XysCollectionzsCollectionY 中的 OneToMany 属性,如下所示:

@Entity
public class X {
    ...
    @OneToMany(mappedBy="xId")
    private List<Y> ysCollection;
    ...
}

如果我误解了您的目标,请告诉我:

X xObj;
CriteriaQuery<Z> cq = cb.createQuery(Z.class);
Root<X> root = cq.from(X.class);
Join<X, Y> ys = root.join("ysCollection");
Join<Y, Z> zs= ys.join("zsCollection");
cq.distinct(true);
cq.where(cb.equal(root.get("id"), xObj.getId()));
cq.select(zs);

或者,使用元模型:

X xObj;
CriteriaQuery<Z> cq = cb.createQuery(Z.class);
Root<X> root = cq.from(X.class);
Join<X, Y> ys = root.join(X_.ysCollection);
Join<Y, Z> zs= ys.join(Y_.zsCollection);
cq.distinct(true);
cq.where(cb.equal(root.get(X_.id), xObj.getId()));
cq.select(zs);
于 2013-03-26T19:29:45.207 回答