我一直在寻找,我还没有找到对我的问题的任何回应。
我在JSF,EclipseLink,Glassfish中创建一个应用程序,用户可以在其中拥有一个或多个组。该应用程序包含以下模块和权限:
我正在寻找一个标准查询(不是在jqpl中)来获取用户的所有模块。我构建了我的SQL查询,其功能非常好:
SELECT *
FROM core_module m
WHERE m.id IN (
SELECT m.id
FROM core_module m
INNER JOIN modules_permissions mp
ON mp.modules_id = m.id
INNER JOIN core_permission p
ON p.id = mp.permissions_id
INNER JOIN users_permissions up
ON p.id = up.permissions_id
INNER JOIN core_user u
ON u.id = 1
)
OR m.id IN (
SELECT m.id
FROM core_module m
INNER JOIN modules_permissions mp
ON m.id = mp.modules_id
INNER JOIN core_permission p
ON p.id = mp.permissions_id
INNER JOIN groups_permissions gp
ON gp.permissions_id = p.id
INNER JOIN core_group g
ON g.id = gp.groups_id
INNER JOIN users_groups ug
ON g.id = ug.groups_id
INNER JOIN core_user u
ON u.id = ug.users_id
WHERE u.id = 1
)
我正在尝试以某种方式将其转换为标准查询而没有取得很大成功。我刚刚开始查询的第一部分,它为我提供了用户可以立即访问的模块。我的印象是我缺少一些条件或加入,因为当我不应该得到任何条件或加入时,我得到2个结果。实际上,我还没有能够包含我的ON
条款,所以我无法在查询中更改我的联接,因为实体不存在:表格{{1 }}是由我的实体中的modules_permissions
创建的......
这是我的第一个子查询草案:
@ManyToMany
答案 0 :(得分:2)
尝试将EclipseLink日志记录设置为最佳,以便{(3}}生成SQL。您可能也使用JPQL,因为它更接近SQL,然后在您有工作后转换为条件。像
这样的东西"select m from Module m where
m in (select m1 from Module m1 join m1.permissions p join p.users u where u.id = 1) or
m in (select m2 from Module m2 join m2.permissions p2 join p2.groups g join g.users u2 where u2.id =1)"
这里的关键是您在条件查询中使用实体关系,以便它与生成的SQL中的内容匹配。如果只希望这些表及其连接包含在内部查询中,请不要使用多个from子句。如果上面的JPQL工作并且存在关系,那么这样的东西是等价的:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Path path = root_module.get(Module_.id);
Subquery<Integer> subquery = criteriaQuery.subquery(Integer.class);
Root subRoot = subquery.from(Module.class);
subquery.select(subRoot.get((Module_.id)));
Join user1 = subRoot.join(Module_.permissions).join(Permission_.users);
subquery.where(criteriaBuilder.equals(user1.get(User_.id), 1));
Subquery<Integer> subquery2 = criteriaQuery.subquery(Integer.class);
Root subRoot2 = subquery.from(Module.class);
subquery2.select(subRoot2.get((Module_.id)));
Join user2 = subRoot2.join(Module_.permissions).join(Permission_.groups).join(Group_.users);
subquery2.where(criteriaBuilder.equals(user2.get(User_.id), 1));
query.where(criteriaBuilder.or(criteriaBuilder.in(path ).value(subquery),
criteriaBuilder.in(path ).value(subquery2)));
答案 1 :(得分:1)
最终答案是:
:
@NamedQuery(name = "core_user.findModuleAssociated", query = "select m from Module m where m.id in (select m1.id from Module m1 join m1.permissions p join p.user u where u.id = :userid) or m.id in (select m2.id from Module m2 join m2.permissions p2 join p2.group g join g.users u2 where u2.id = :userid)")
:
List<Module> modules;
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Path path = root_module.get(Module_.id);
Subquery<Integer> subquery = query.subquery(Integer.class);
Root subRoot = subquery.from(Module.class);
subquery.select(subRoot.get((Module_.id)));
Join user1 = subRoot.join(Module_.permissions).join(Permission_.user);
subquery.where(cb.equal(user1.get(User_.id), current.getId()));
Subquery<Integer> subquery2 = query.subquery(Integer.class);
Root subRoot2 = subquery.from(Module.class);
subquery2.select(subRoot2.get((Module_.id)));
Join user2 = subRoot2.join(Module_.permissions).join(Permission_.group).join(Group_.users);
subquery2.where(cb.equal(user2.get(User_.id), current.getId()));
query.where(cb.or(cb.in(path).value(subquery), cb.in(path).value(subquery2)));
modules = getEntityManager().createQuery(query).getResultList();
特别感谢Chris