JPA标准加入et ON

JPA标准加入et ON,jpa,glassfish,eclipselink,criteria,builder,Jpa,Glassfish,Eclipselink,Criteria,Builder,我已经搜索了一段时间,我没有找到任何对我的问题的回应 我正在用JSF、EclipseLink和Glassfish制作一个应用程序,用户可以在其中拥有一个或多个组。该应用程序包含以下模块和权限: 模块=>权限=>使用权限 模块=>permission=>groupe=>Usilizateur 我正在寻找一个不在jqpl中的条件查询来获取用户的所有模块。我已经构建了我的SQL查询,它的功能非常好,如下所示: 挑选* 从核心模块m m.id在哪里 选择m.id 从核心模块m 内部联接模块 关于mp.m

我已经搜索了一段时间,我没有找到任何对我的问题的回应

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

模块=>权限=>使用权限 模块=>permission=>groupe=>Usilizateur 我正在寻找一个不在jqpl中的条件查询来获取用户的所有模块。我已经构建了我的SQL查询,它的功能非常好,如下所示:

挑选* 从核心模块m m.id在哪里 选择m.id 从核心模块m 内部联接模块 关于mp.modules_id=m.id 内部连接核心\p ON p.id=mp.permissions\u id 内部加入用户\u权限增加 ON p.id=up.permissions\u id 内部连接核心用户 在u.id=1时 或者m.id 选择m.id 从核心模块m 内部联接模块 在m.id=mp.modules\u id上 内部连接核心\p ON p.id=mp.permissions\u id 内部联接组\u权限gp 关于gp.id\u id=p.id 内连接核心组g 关于g.id=gp.groups\u id 内部连接用户组 关于g.id=ug.groups\u id 内部连接核心用户 ON u.id=ug.users\u id 其中u.id=1 我试图以某种方式将其转换为条件查询,但没有取得很大成功。我刚刚开始查询的第一部分,它为我提供了用户可以立即访问的模块。我的印象是我缺少了一些条件或连接,因为我得到了两个结果,而我不应该得到任何结果。实际上,我无法包含我的ON子句,因此我无法在查询中更改我的to联接,因为实体不存在:表模块\u权限是由实体中的@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();

尝试将EclipseLink日志记录转换为finest,以便您可以查看生成的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)));
最后的答案是:

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

特别感谢克里斯

嗨,阿尔奇,这是一个讲英语的论坛。我试图翻译你的问题。以后,请用英语发布您的问题和答案。非常感谢您的翻译!Criteria builder有一个问题=>ejb例外llégal使用getField[core_module.ID]un表达式生成的SQL是什么,它与从JPQL创建的SQL有何不同?没有生成SQL。直接执行EJB异常。尽可能简化查询,然后逐个添加回子句,直到找到导致错误的原因。您还应该发布完整的异常堆栈跟踪,并尝试最新的Eclipselink版本2.5.1