JPQL,如何不选择某些东西

Posted

技术标签:

【中文标题】JPQL,如何不选择某些东西【英文标题】:JPQL, How to NOT select something 【发布时间】:2010-12-07 09:51:32 【问题描述】:

我需要执行一个非常简单的 SQL。

我有一个ProcessUserRole 和一个ProcessUserRole 表。直接的多对多

我想选择所有具有管理员角色的ProcessUser

但是我的 JPQL 失败了,因为我的用户也有角色官员,所以它在列表中被检索到。

这是 JPQL:

entityManager.createQuery("SELECT p FROM " + ProcessUser.class.getName() 
  + " p join p.roles role WHERE role.name NOT IN ('sysadmin')").getResultList();

生成的SQL是:

选择 不同的 processuse0_.id 为 id8_, 处理使用0_.position 作为 position8_, processuse0_.username 作为 username8_, processuse0_.organization_id 作为organiza9_8_, 进程使用0_.passwordHash 作为密码4_8_, 进程使用0_.fromEmail作为fromEmail8_, processuse0_.firstname 作为 firstname8_, processuse0_.lastname 作为 lastname8_, processuse0_.processes 作为 processes8_ 从 ProcessUser 进程use0_ 内部联接 ProcessUserRoles 角色1_ 在 processuse0_.id=roles1_.userId 内部联接 角色role2_ 在角色1_.roleId=role2_.id 在哪里 ( role2_.name 不在 ( '系统管理员' ) )

【问题讨论】:

您说要包含 ADMIN 角色,但您的示例显示 ROLE NAME NOT IN SysAdmin。你能解释一下吗? @Shervin - 你需要小心你的标签;以下大多数答案不正确,因为您已将问题标记为“SQL”(现已更改为 JPQL) 不,我不想包含管理员 (sysadmin)。 ProcessUser 是用户和系统管理员,因此我的选择没有得到我想要的。如果具有系统管理员角色,我希望用户被省略。 【参考方案1】:

这对你有用吗?

SELECT *
FROM ProcessUser
WHERE Exists
(
    SELECT 1
    FROM 
        ProcessUserRoles
        INNER JOIN Roles
            ON Roles.RoleId = ProcessUserRoles.RoleId
    WHERE 1=1
        AND ProcessUser.ProcessUserId = ProcessUserRoles.ProcessUserId
        AND Roles.RoleDescription = 'Super User'
)

【讨论】:

这是直接的 SQL,不是 JPQL。【参考方案2】:

运行嵌套查询。首先选择所有具有 sysadmin 角色的用户。然后选择这个的补集,或者所有不在这个结果中的用户。

【讨论】:

【参考方案3】:

您的查询基本上是带回一个用户/角色列表,因为您的用户有两个角色,他回来了两次,您通过排除“系统管理员”的角色来过滤掉一行。听起来您想要做的是排除所有具有“系统管理员”角色的用户,无论他们是否有其他角色。您需要在查询中添加一些内容,例如。 (我是根据您的查询而不是您的描述)

  where processuse0_.id not in 
  select ( userId  from 
           ProcessUserRoles
           inner join 
           Role 
           on ProcessUserRoles.roleId=Role.id 
           where role.name != 'sysadmin'

           )

【讨论】:

再说一遍,这是 SQL,不是 JPQL。 @ChssPly76 好吧,希望发布的 sql 将指向正确的方向来修复他的 JPQL,尤其是因为没有人提供 JPQL 解决方案。事实上,在您指出其他人的回复不是 JPQL 后 50 分钟,您才发帖 您的回答中可能应该提到“希望”。请注意,我没有对您投反对票;我只是指出这并不是 OP 问题的有效解决方案。就“50 分钟后”而言,我一直在等着看你或这个线程中的其他任何人是否会在我的 cmets 之后包含 JPSQL 之后真正更新他们的答案,这样我就可以投票给他们,我只在之后发布了我的答案那没有发生。 @ChssPly76 他列出了生成的sql并将问题标记为sql,你怎么知道他不是也在寻求帮助理解生成的sql?也许你不应该删除 sql 标签。 谢谢你。我实际上是在寻找 jpql,但是 sql 也很好,因为我可以将它翻译成 jpql。谢谢。【参考方案4】:

使用子查询的正确 JPQL 语法:

SELECT p FROM ProcessUser p
 WHERE p.id  NOT IN (
  SELECT p2.id FROM ProcessUser p2
    JOIN p2.roles role
   WHERE role.name='sysadmin'
 )

【讨论】:

谢谢,这几乎成功了,但是正确的是 WHERE role.name =='sysadmin' 因为你已经在说 NOT IN 我的意思是说 role.name = 'sysadmin'【参考方案5】:

JPQL:

TypedQuery<ProcessUser> query = em.createQuery("" +  
   " SELECT p FROM ProcessUser p " +
   " WHERE p.roles.name <> ?1", ProcessUser.class);
query.setParameter(1, "sysadmin");
return query.getResultList;

【讨论】:

以上是关于JPQL,如何不选择某些东西的主要内容,如果未能解决你的问题,请参考以下文章

在 JPQL 中可以选择 EXISTS() 吗?

如何在jpql中选择列表元素的属性

如何在 Spring JpaRepository 中使用 JPQL 选择组中的最新记录?

JPQL如何总结孩子的给定属性并获取这些孩子避免n + 1个选择?

如何仅检索 JPQL 或 HQL 中实体的某些字段? JPQL 或 HQL 中的 ResultSet 等价物是啥?

JPQL 选择内部选择