【问题标题】:NHibernate How to Select distinct objects based on specific property using HQL?NHibernate如何使用HQL根据特定属性选择不同的对象?
【发布时间】:2010-12-20 11:51:22
【问题描述】:

如何使用 HQL 来选择满足特定条件的特定对象?

我们尝试了以下方法来生成前十个订阅的 RSS 提要列表(其中 SubscriptionCount 是派生属性):

var topTen = UoW.Session.CreateQuery( @"SELECT distinct rss 
                                                 FROM RssFeedSubscription rss
                                                 group by rss.FeedUrl
                                                 order by rss.SubscriptionCount DESC
                                                 ")
.SetMaxResults(10)
.List<RssFeedSubscription>();

目的只是选择数据库中的两个唯一提要 URL,而不是数据库中实例化为对象的十行。上面的结果是:

Column 'RssSubscriptions.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

有可能只是精简结果,以便我们在从数据库中取回数据后取出两个唯一的提要 URL,但是必须有一种方法可以在数据库级别使用 HQL 做到这一点吗?

编辑:我们意识到可以进行标量查询,然后手动提取值,但是没有办法简单地为拉回的对象指定匹配条件吗?

【问题讨论】:

    标签: nhibernate hql


    【解决方案1】:

    group by rss.FeedUrl 导致您出现问题。看起来您不需要它,因为您正在选择实体本身。删除它,我认为你会很好。

    编辑 - 抱歉,我没有注意到有关“派生属性”的部分。我假设您的意思是它不是 Hibernate 映射的属性,因此表中实际上没有列?这将解释您在查询中收到的第二条错误消息。如果是这种情况,您可能还需要删除“order by”子句并在 Java 中进行排序。

    【讨论】:

    • 是的,这会导致异常,但删除它仍然不会产生我们正在寻找的结果
    【解决方案2】:

    如果你稍微改变你的 HQL 看起来像这样:

    var topTen = UoW.Session.CreateQuery( @"SELECT distinct rss.FeedUrl
                                              FROM RssFeedSubscription rss
                                              group by rss.FeedUrl
                                              order by rss.SubscriptionCount DESC
                                            ")
    .SetMaxResults(10)
    .List();
    

    topTen 变量将是一个 object[],其中包含 2 个元素,其中有 2 个提要 URL。

    如果您使用 IQuery 接口的 SetResultTransformer() 方法,则可以将此作为强类型集合返回。

    【讨论】:

      【解决方案3】:

      您需要执行一个标量查询。这是 NHibernate 文档中的一个示例:

      IEnumerable results = sess.Enumerable(
          "select cat.Color, min(cat.Birthdate), count(cat) from Cat cat " +
          "group by cat.Color"
      );
      foreach ( object[] row in results )
      {
          Color type = (Color) row[0];
          DateTime oldest = (DateTime) row[1];
          int count = (int) row[2];
          .....
      }
      

      【讨论】:

      • 是的,我们也尝试过这种方式,但认为作为 SQL 调用的一部分可能会有更简洁的方式。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-08
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      • 1970-01-01
      • 2012-12-14
      • 1970-01-01
      相关资源
      最近更新 更多