【问题标题】:JPQL, How to NOT select somethingJPQL,如何不选择某些东西
【发布时间】: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 是用户和系统管理员,因此我的选择没有得到我想要的。如果具有系统管理员角色,我希望用户被省略。

标签: jpa jpql


【解决方案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;
    

    【讨论】:

      猜你喜欢
      • 2012-12-10
      • 2018-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 2023-03-08
      • 2017-01-31
      相关资源
      最近更新 更多