JPQL,如何不选择某些东西
Posted
技术标签:
【中文标题】JPQL,如何不选择某些东西【英文标题】:JPQL, How to NOT select something 【发布时间】:2010-12-07 09:51:32 【问题描述】:我需要执行一个非常简单的 SQL。
我有一个ProcessUser
、Role
和一个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,如何不选择某些东西的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring JpaRepository 中使用 JPQL 选择组中的最新记录?
JPQL如何总结孩子的给定属性并获取这些孩子避免n + 1个选择?