我使用 hibernate / JPA实施服务器端数据分页,底层数据库是 MS SQL Server 2008。
SQL生成如下:
criteria.setFirstResult(pagingParams.getDisplayStart())
.setMaxResults(pagingParams.getDisplayLength());
(主要工作在于创建适当的过滤器/排序,但这与此无关)
我正在观察的是以下SQL:
page (0-20):
select top 20 this_.id as id11_9_,...
page (20-40):
select top 40 this_.id as id11_9_,...
page (40-60):
select top 60 this_.id as id11_9_,...
......等等。
显然,如果基础结果集太大而且(b)与分页没什么关系,那么(a)将遇到严重问题: - (
有同样问题的人?
更新:好像是Tiber的Row_Number()
函数的NHibernate(Hibernate的.NET实现)takes advantage。遗憾的是Hibernate没有...
答案 0 :(得分:8)
有点迟到的回复,但它可能会有所帮助,所以我会发布它。有完全相同的问题和头痛来追踪它。解决方案是使用Hibernate 4.3.0中包含的org.hibernate.dialect.SQLServer2012Dialect
。生成的查询变为(粘贴没有列名和别名的真实Hibernate转储):
WITH query
AS (SELECT inner_query.*,
Row_number()
OVER (
ORDER BY CURRENT_TIMESTAMP) AS __hibernate_row_nr__
FROM (SELECT TOP(?) <COLUMN_NAMES> AS <ALIASES>
FROM <TABLE_NAME>
) inner_query)
SELECT <ALIASES>
FROM query
WHERE __hibernate_row_nr__ >= ?
AND __hibernate_row_nr__ < ?
注意内部查询和Row_number()
函数的用法。他们终于解决了!
答案 1 :(得分:4)
我们也观察到Hibernate 3.3与hibernate.dialect=org.hibernate.dialect.SQLServerDialect
(使用SQL Server 2008 R2)的相同行为。
我的印象是,当使用Hibernate&gt; = 3.5,将hibernate.dialect
设置为org.hibernate.dialect.SQLServer2005Dialect
或org.hibernate.dialect.SQLServer2008Dialect
,使用SQL Server&gt; = 2005时,此性能问题就消失了可能还有SQL Server驱动程序JDBC&gt; = 3.0。
备用上述展示的其他链接:
Row_Number()
function,我假设现在支持它。答案 2 :(得分:2)
这是因为MSSQL没有为此版本提供真正的分页实现。确实有可能在Row_Number()中使用内部查询,但就像你提到的那样,Hibernate不使用它。
我发现某些人修改了SQLServer2008Dialect.java以使其使用Row_Number()。 follow this link
编辑:(我注意到这些文件的来源不再可用)
在MSSQL2012中,应解决此问题,因为它们实现了分页功能。剩下的唯一问题是这个版本的MSSQL没有特定的方言。他们建议使用旧的(MSSQL2008),但这会导致相同的分页问题。