2010-05-24 64 views
4

我对hql还是有点新,并且对于我正在编写的查询有一个关于聚合函数和效率的问题。获取hql中成员值最高的对象?

比方说,我有这个类在Hibernate映射(getter/setter方法/构造函数/等不再赘述。):

public class Foo 
{ 
    private int i; 

    private String s; 

    private float f; 
} 

我想做一个HQL查询来获取最高的我的富实例值和指定的f值。我目前的解决办法是这样的:

List<Foo> fooList = (List<Foo>)session.createQuery(
    "from Foo as foo where foo.s = :str and foo.f = :val order by foo.i desc"). 
    setParameter("str", <stringgoeshere>).setParameter("val", <floatgoeshere>). 
    list(); 
return fooList.get(0); 

如果我理解正确的话,这种方法将有N+1 selects problem(虽然只要我只是抓住从列表中的第一个结果,N有望为1,但仍然) 。我假设有一些方法可以用uniqueResult()来做到这一点,但我不太明白在这种情况下聚合函数是如何工作的。我已经能够找到的“max()”的唯一示例是在where子句或返回的值中。

我应该如何编写这个查询来在单个select中完成它,并抓取具有最高i的Foo实例?

感谢您的帮助!

回答

2

如果我理解正确的话,这种方法将有N + 1查询问题

我没有看到你的查询可以如何导致n + 1种选择。 Hibernate没有理由迭代第一个查询的结果并在这里执行后续查询。

我假设有一些方法可以用uniqueResult()来做到这一点,但我不太明白在这种情况下聚合函数是如何工作的。

如果你想获取一个结果,这将是确实聪明,检索整个表。首先,查询会更有效率,其次,你不会浪费任何东西的内存(甚至可能使会话爆炸)。如果您的表格包含一百万条记录会怎么样?

我应该如何编写这个查询来做到这一点在一个单一的选择,并抓住最高的我的Foo实例?

正如刚才提到的,只检索需要的记录,使用setMaxResults(1)限制结果的数量(这取决于你的数据库上会产生正确的SQL命令):

Foo foo = (Foo) session.createQuery(
    "from Foo as foo where foo.s = :str and foo.f = :val order by foo.i desc") 
    .setParameter("str", <stringgoeshere>).setParameter("val", <floatgoeshere>) 
    .setMaxResults(1) 
    .uniqueResult(); 
return foo; 
+0

嗯,所以即使你使用uniqueResult,您仍然需要将最大结果设置为1,否则它将拉出所有记录?很高兴知道,我认为它足够聪明,可以自动执行此操作。 – serg 2010-05-24 20:53:33

+0

刚刚注意到你对上面的评论:) – serg 2010-05-24 20:54:40

+0

虽然我的代码最终会做2选择:一个为.list()和一个为.get(0)。情况并非如此吗? – Seth 2010-05-24 21:00:52