我试图避免为计数创建一个单独的查询,为实际查询创建一个单独的查询。我发现 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/