2014-03-01 58 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