5

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

备选方案 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

备选方案 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

如果我跳过获取所有模板的要求,我可以简单地使用用户和配置文件作为根,以下就足够了:

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();

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

该任务当然可以通过迂回的方式解决,例如执行第二个查询,选择所有模板并将其与第一个查询的结果合并,但如果可以在单个查询中完成,那将创建更清晰的代码。

4

0 回答 0