2014-03-01 57 views
2

我一直在寻找一段时间,我还没有找到任何回应我的问题。JPA标准JOIN et ON

我提出在JSF,的EclipseLink,Glassfish的应用程序中,用户可以有一个或多个组。该应用程序包含模块和权限如下:

  • 模块=>权限=> utilisateur
  • 模块=>权限=> GROUPE => utilisateur

我寻找条件查询(未在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条款,所以我不能改变我对联接我的查询中,因为不存在的实体:表modules_permissions是由我的实体@ManyToMany创建...

这是我的第一个子查询草案:

List<Module> modules; 
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); 
CriteriaQuery<Module> query = cb.createQuery(Module.class); 

Root<Module> root_module = query.from(Module.class); 
Root<User> root_user = query.from(User.class); 
Root<Permission> root_permission = query.from(Permission.class); 
Root<Group> root_group = query.from(Group.class); 

Join<Module, Permission> join_module_permission = root_module.join(Module_.permissions); 
Join<Permission, User> join_permission_user = root_permission.join(Permission_.users); 
query.where(cb.equal(root_user.get(User_.email), current.getEmail())); 
modules = getEntityManager().createQuery(query).getResultList(); 
+0

嗨Archi,这是一个讲英语的论坛。我试图翻译你的问题。今后,请以英文发布您的问题和答案。 –

+0

非常感谢翻译! – Archi

回答

1

最终的答案是:

  • 在JPQL:

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

特别感谢克里斯

2

尝试打开的EclipseLink日志记录,以最优秀的,所以你可以see所生成的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想要什么。如果只希望将这些表和它们的联接包含在内部查询中,请不要使用multiple 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))); 
+0

嘿,非常感谢! JPQL查询工作正常。 – Archi

+0

标准构建器有问题=> EJB异常 – Archi

+0

非法使用getfield命令的()[core_module.ID]未表达 – Archi