我在主查询和子查询中明确定义了WHERE语句。如果省略子查询,则会在JPA日志中打印。但是,如果我添加子查询,则不应用相同的where子句。什么是JPA Criteria查询,省略了WHERE子句(选择σ)?
// 1) MainQuery
// Create the FROM
Root<PubThread> rootPubThread = cq.from(PubThread.class);
// Create the JOIN fro the first select: join-chaining. You only need the return for ordering. e.g. cq.orderBy(cb.asc(categoryJoin.get(Pub_.title)));
Join<Pub, PubCategory> categoryJoin = rootPubThread.join(PubThread_.pups).join(Pub_.pubCategory);
// Create the WHERE
cq.where(criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)));
// Create the SELECT, at last
cq.select(rootPubThread).distinct(true);
// 2) Subquery
Subquery<PubThread> subquery = cq.subquery(PubThread.class);
Root<PubThread> rootPubThreadSub = subquery.from(PubThread.class);
subquery.where(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId));
Join<Pub, PubCategory> categoryJoinSub = rootPubThreadSub.join(PubThread_.pups).join(Pub_.pubCategory);
subquery.select(rootPubThreadSub);
Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
subquery.where(correlatePredicate);
cq.where(criteriaBuilder.exists(subquery));
以下是此查询的输出:
select distinct
pubthread0_.id as id3_,
pubthread0_.dateCreated as dateCrea2_3_,
pubthread0_.dateModified as dateModi3_3_,
pubthread0_.name as name3_
from
pubthread pubthread0_
inner join
pub_pubthread pups1_ ON pubthread0_.id = pups1_.pubThreads_id
inner join
pub pub2_ ON pups1_.pups_id = pub2_.id
inner join
PubCategory pubcategor3_ ON pub2_.pubCategoryId = pubcategor3_.id
where
exists( select
pubthread4_.id
from
pubthread pubthread4_
inner join
pub_pubthread pups5_ ON pubthread4_.id = pups5_.pubThreads_id
inner join
pub pub6_ ON pups5_.pups_id = pub6_.id
inner join
PubCategory pubcategor7_ ON pub6_.pubCategoryId = pubcategor7_.id
where
pubthread4_.id=pubthread0_.id)
答案 0 :(得分:0)
知道了。一旦定义了谓词,where子句就会被拒绝。这是肯定的。将where子句与Predicate
实例中的连接组合,并将其附加到where子句中。使用criteriaBuilder.and(..., ...)
。从语义上做同样的事情。
现在,有两个连接谓词:一个用于子查询,一个用于主查询。请注意我从代码中排除的过时单select(...)
(已注释)。
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<PubThread> mainQuery = criteriaBuilder
.createQuery(PubThread.class);
// 1) MainQuery
// Create the FROM
Root<PubThread> rootPubThread = mainQuery.from(PubThread.class);
// Create the JOIN from the first select: join-chaining. You only need the return for ordering. e.g. cq.orderBy(cb.asc(categoryJoin.get(Pub_.title)));
Join<Pub, PubCategory> categoryJoin = rootPubThread.join(PubThread_.pups).join(Pub_.pubCategory);
// Create the WHERE
mainQuery.where(criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)));
// Create the SELECT, at last
mainQuery.select(rootPubThread).distinct(true);
// 2) Subquery
Subquery<PubThread> subquery = mainQuery.subquery(PubThread.class);
Root<PubThread> rootPubThreadSub = subquery.from(PubThread.class);
//subquery.where(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId));
Join<Pub, PubCategory> categoryJoinSub = rootPubThreadSub.join(PubThread_.pups).join(Pub_.pubCategory);
subquery.select(rootPubThreadSub);
//Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
Predicate correlatePredicate = criteriaBuilder.and(
criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread),
criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)
);
subquery.where(correlatePredicate);
//Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
Predicate mainPredicate = criteriaBuilder.and(
criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)),
criteriaBuilder.exists(subquery)
);
//cq.where(criteriaBuilder.exists(subquery));
mainQuery.where(mainPredicate);
TypedQuery<PubThread> typedQuery = em.createQuery(mainQuery);
List<PubThread> otherPubThreads = typedQuery.getResultList();
return otherPubThreads;
结果是这样的
where
pubthread4_.id=pubthread0_.id
and pubthread0_.id=1