【问题标题】:HQL to get elements that possess all items in a setHQL 获取拥有集合中所有项目的元素
【发布时间】:2010-05-21 02:05:34
【问题描述】:

目前,我有一个 HQL 查询,它返回从一组指定奖项中获得 ANY 奖项的所有会员:

from Member m left join m.awards as a where a.name in ("Trophy","Ribbon");

我现在需要的是 HQL,它将返回所有拥有 ALL 奖励的会员,这些奖励在一组奖励中指定。

所以,假设这个数据:

Joe has Trophy, Medal
Sue has Trophy, Ribbon
Tom has Trophy, Ribbon, Medal

上面的查询将返回 Joe、Sue 和 Tom,因为这三个人都至少拥有 Trophy 或 Ribbon 之一。但我只需要归还 Sue 和 Tom,因为他们是唯一拥有所有指定奖项(奖杯和丝带)的人。

这是类结构(简化):

class Member {
  private String name;
  private Set<Award> awards;
}
class Award {
  private String name;
}

【问题讨论】:

    标签: java hibernate hql


    【解决方案1】:
    select m from Member m left join m.awards as a where a.name in ("Trophy","Ribbon") group by m having count(a)=2
    

    【讨论】:

    • @serg555 - 不错!应该是 count(a)=2 还是 count(2)>=2 ?另外,有没有办法在没有 group by/having 子句的情况下做到这一点?我的实际查询非常复杂,包括 where 子句、order by 子句、多个子查询等。我还需要运行相同的查询,但使用 count(*) 来获取返回的记录数。在使用 group by 子句时遇到问题。
    • 应该是count(a)=2。抱歉,我不知道没有分组的替代解决方案。
    • @serg555:好的,谢谢。我遇到的问题是,当我在 count(*) 查询中包含 group by/have 时,我没有得到唯一的结果。所以 countQuery.uniqueResult() 失败。我需要获取分页控件的结果总数。
    • 您可以在查询中添加 distinct。 select distinct m from Member m ...select count(distinct m.id) from ...
    • @serg555:这正是我正在做的事情:select count(distinct m.id) from ...。但是对于 group by,uniqueResults() 会引发异常。例如,常规查询返回 4 个成员对象:[Member, Member, Member, Member]count() 版本的查询返回一个包含 4 个元素的数组:[1,1,1,1]。我认为这是因为每个“组”的大小为 1。有什么想法吗?
    【解决方案2】:

    只是重复我自己... 获取拥有给定奖励集合的成员的代码:

    from Member m 
    where not exists (
      from Award a where a.name in {"Trophy", "Ribbon"} 
      and a not in( 
        select * from Award a2 where a2.owner = m 
      ) 
    ) and not exists ( 
      from Award a3 where a3.owner = m and a3 not in {"Trophy", "Ribbon"} 
    ) 
    

    【讨论】:

    • (所以原问题的答案是第一个不存在。)
    • 这个有一个小故障:它只适用于 Award#names。例如,如果您对集合 {"Trophy", "Handshake"} 执行相同的操作,并且没有名为“Handshake”的 Award:它不会按预期返回一个空结果集,而是返回一个结果,好像单元素集 {"Trophy"} 是参数。
    • (要纠正这个故障:您需要一个包含所有可能的奖项名称的表,并且第一个不存在的应该是“来自”该实体。在 native-sql 中,joined-union 可以解决这个,在 hql 中:我们没有找到更好的)
    【解决方案3】:

    您可以通过向查询调用 IE 添加一个 DISTINCT_ROOT_ENTITY 结果转换器来强制不同的结果:

    getSession().createQuery(hql).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
    

    我遇到了类似的问题,但我需要做的是(按照您的示例)选择所有成员,他们拥有所有奖项,仅此而已。因此,在您的示例中,唯一正确的结果是 Sue。有任何想法吗?

    【讨论】:

      猜你喜欢
      • 2015-06-18
      • 1970-01-01
      • 2018-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-24
      相关资源
      最近更新 更多