java - hibernate 是否支持 count(*) over()

标签 java sql hibernate window-functions

我试图避免为计数创建一个单独的查询,为实际查询创建一个单独的查询。我发现 SessionImpl::createQuery 需要花费大量时间进行复杂查询,然后通过结合计数和主查询,我可以消除一个 createQuery 调用。

在 SQL 中我可以做类似的事情

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

hibernate可以实现吗?

(我试图避免使用原生 sql 并坚持使用 HQL 和分离条件。使用原生 SQL 违背了使用 hibernate 的目的。我的系统必须同时支持 Oracle 和 Sybase)

最佳答案

Hibernate 的 @Formula注释可以作为一种解决方法。在您的 @Entity 中提供一个额外的列来表示计数,用 @Formula 注释,其中包含 COUNT OVER 查询:

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

不过,使用这种方法,Hibernate 会略微处理生成的 SQL,因此您可能还需要注册一个 Interceptor。清理 SQL:

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 () ");
    }

}

除了显式的 Hibernate 依赖项(而不是纯 JPA)之外,还有一个缺点,即默认情况下将加载此列,这可能会在不需要计数的查询中增加一些不必要的开销。可以将列设为可选,lazily loaded ,但这需要字节码检测并进一步增加了复杂性。

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

关于java - hibernate 是否支持 count(*) over(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21616691/

相关文章:

java - Hibernate Criteria.list() 发出 "ORA-01401: inserted value too large for column"错误

java - 从数组列表中删除一个项目

java - 验证代码是否在 Vaadin 7 应用程序的用户界面线程上运行

java - java调用2个类时出错

java - 在 Android 上将 UTC 转换为本地时间

mysql - 如何将 varchar 转换为 datetime,不起作用

sql - PostgreSQL 如何删除重复值

java - 如何将返回的对象转换为所需的bean/pojo

mysql - 从 2 个表调用数据

java - 获取导致 com.microsoft.sqlserver.jdbc.SQLServerException : String or binary data would be truncated 的列的任何方法