2010-05-24 61 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