JPA Criteria JOIN et ON

时间:2014-03-01 11:52:11

标签: jpa glassfish eclipselink criteria builder

我一直在寻找,我还没有找到对我的问题的任何回应。

我在JSF,EclipseLink,Glassfish中创建一个应用程序,用户可以在其中拥有一个或多个组。该应用程序包含以下模块和权限:

  • Module => permission => utilisateur
  • Module => permission => 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条款,所以我无法在查询中更改我的联接,因为实体不存在:表格{{1 }}是由我的实体中的modules_permissions创建的......

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

@ManyToMany

2 个答案:

答案 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)

最终答案是:

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

特别感谢Chris