我正在尝试阻止为count创建一个单独的查询,为实际查询创建一个查询。我发现SesssionImpl :: createQuery需要相当长的时间来进行复杂的查询,通过组合count和主查询,我可以消除一个createQuery调用。
在SQL中我可以做类似
的事情select count(*) over(), col_A, col_B
from TABLE_XX
where col_C > 1000
这可以在休眠中实现吗?
(我正在尝试避免本机sql并坚持使用HQL和分离标准。使用本机SQL会破坏使用hibernate的目的。我的系统必须同时支持Oracle和Sybase)
答案 0 :(得分:2)
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;
答案 1 :(得分:1)
您可以将其用于: -
return (Number) session.createCriteria("Book").setProjection(Projections.rowCount()).uniqueResult();