使用JPA 2 Criteria API加入特定的ON子句

Ras*_*nke 5 criteria-api java-ee-6 jpa-2.0

以某种方式可以使用JPA 2 Criteria API执行以下查询之一吗?基本上,Profiles使用了许多模板.系统中的每个用户都有任意数量的配置文件和两个活动配置文件.我想获取所有模板以及拥有使用它的活动配置文件的用户数.

备选方案1

SELECT t.id, count(p.id)
FROM template t
LEFT JOIN profile p ON p.template_id = t.id
LEFT JOIN users u ON (u.active_profile_id = p.id OR u.active_personal_profile_id = p.id)
GROUP BY t.id
Run Code Online (Sandbox Code Playgroud)

备选方案2

SELECT t.id, count(p.id)
FROM COMPETENCE.template t
LEFT JOIN COMPETENCE.profile p ON (p.template_id = t.id)
LEFT JOIN users u1 on u1.active_profile_id = p.id
LEFT JOIN users u2 on u2.active_personal_profile_id = p.id
GROUP BY t.id
Run Code Online (Sandbox Code Playgroud)

如果我跳过了获取所有模板的要求,我可以简单地使用User和Profile作为Roots,以下就足够了:

CriteriaQuery<Tuple> cq = cb.createTupleQuery();
Root<User> from = cq.from(User.class);
Root<Profile> from2 = cq.from(Profile.class);
Join<Profile, Template> join = from2.join(Profile_.template);
cq.where(cb.or(
             cb.equal(from.get(User_.activeCompetenceProfile), from2),
             cb.equal(from.get(User_.activePersonalProfile), from2)
));
cq.groupBy(join.get(Template_.id));
cq.multiselect(join.get(Template_.id), cb.count(from2.get(Profile_.id)));
List<Tuple> tuples = em.createQuery(cq).getResultList();
Run Code Online (Sandbox Code Playgroud)

但是为了获得所有模板,我相信我不能使用WHERE子句,但是在第一次查询中需要外连接.但是,备选方案1似乎不可能,因为您无法为连接设置特定的ON子句,而备选方案2似乎不可能,因为用户和模板都需要同时为Root.要获取所有模板,我需要使用模板作为root,并将其与Profile连接.这很顺利,但由于ON参数存储在User而不是Profile中,因此我无法加入Profile with User.据我所知,你不能在第二个表中存储的参数上与另一个表连接.

该任务当然可以通过循环方式解决,例如选择所有模板进行第二次查询并将其与第一个查询的结果合并,但如果可以在单个查询中进行,则可以创建更清晰的代码.