2014-03-01 5 views
2

잠시 동안 검색했지만 문제에 대한 응답을 찾지 못했습니다.JPA Criteria JOIN et ON

사용자가 하나 이상의 그룹을 가질 수있는 JSF, EclipseLink, Glassfish에서 응용 프로그램을 만들고 있습니다.

  • 모듈 => 권한 => utilisateur
  • 모듈 => 권한 => Groupe의 => utilisateur 내가 criteria 질의를 찾고 있어요

(하지 : 다음과 같이 응용 프로그램 모듈과 권한을 포함 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

당신이 생성되는 SQL을 see 수 있도록 최상의으로는 EclipseLink 로깅을 켜십시오 :

여기 내 첫 번째 초안 하위 쿼리입니다. 또한 SQL에 가깝기 때문에 JPQL을 사용하고 작업 한 후에는 조건으로 변환 할 수 있습니다. 뭔가 같은 것

"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))); 
+0

안녕하세요, 정말 고마워요 !!! JPQL 쿼리가 정상적으로 작동합니다. – Archi

+0

기준 작성 도구에 문제가 발생했습니다.> ejb 예외 – Archi

+0

getField() [core_module.ID] un expression – Archi