2014-02-06 80 views
5

我試圖阻止必須爲count創建一個單獨的查詢,併爲實際查詢創建一個查詢。我發現SesssionImpl :: createQuery需要大量的時間來處理一個複雜的查詢,並且通過組合count和主查詢,我可以消除一個createQuery調用。休眠支持count(*)over()

在SQL我可以這樣做

select count(*) over(), col_A, col_B 
from TABLE_XX 
where col_C > 1000 

可這在Hibernate可以實現嗎?

(我試圖避免本地SQL,並堅持HQL和分離的標準。使用本機SQL違背了使用休眠的目的。我的系統同時支持Oracle和Sybase)

+1

那麼你可以隨時使用原生的SQL。我假設你想避免這種情況? –

+0

是的,我試圖避免本機SQL和堅持HQL和分離標準。使用本機SQL會破壞使用hibernate的目的。 – user2596860

+0

什麼是您的底層數據庫? –

回答

1

您可以用這個: -

return (Number) session.createCriteria("Book").setProjection(Projections.rowCount()).uniqueResult(); 
2

Hibernate的@Formula註釋可能是一種解決方法。在您的@Entity提供額外的列來表示其中包含COUNT OVER查詢計數,用@Formula註釋:

@Formula("count(*) over()") 
private Integer totalResults; 

通過這種方法,休眠屠夫生成的SQL一點,雖然,所以您可能還需要註冊一個從明確的Hibernate依賴關係(而不是純粹的JPA),還有另外一個缺點,使得該列將被默認加載這可能會增加一些不必要的開銷,查詢

public class CountOverQueryInterceptor extends EmptyInterceptor { 

    private static final long serialVersionUID = -2980622815729060717L; 

    @Override 
    public String onPrepareStatement(String sql) { 
     return super.onPrepareStatement(cleanCountOver(sql)); 
    } 

    /** 
    * Cleans the "{@code count(*) over()}" query fragment from Hibernate's sql 
    * decoration "{@code count(*) <alias>.over()}". 
    */ 
    static String cleanCountOver(String sql) { 
     return sql.replaceAll("(?i) (count)\\(\\*\\) \\w+\\.(over) \\(\\)", " $1(*) $2() "); 
    } 

} 

旁白:Interceptor清理SQL國家t不是必需的。有可能使該列成爲可選項,並且這可能需要字節碼檢測,並增加了更多層次的複雜性。

@Formula("count(*) over()") 
@Basic(optional = true, fetch = FetchType.LAZY) 
private Integer totalResults;