JDBC分页

Zee*_*han 33 java sql pagination jdbc

我想用JDBC实现分页.我想知道的实际情况是"如何从第1页和第2页的数据库中获得前50个然后下50条记录"

我的查询是Select * from data[数据表包含20,000行]

对于第1页,我得到50条记录,对于第2页,我希望获得接下来的50条记录.如何在JDBC中有效地实现它?

我已经搜索过,发现这rs.absolute(row)是跳过第一页记录的方法,但是在大型结果集上花费了一些时间,我不想承受这么多时间.另外,我不想在查询中使用rownumlimit+ offset,因为这些不适合在查询中使用,我不知道为什么,我仍然不想在查询中使用它.

任何人都可以帮助我如何限制ResultSet分页或JDBC是否有任何方式给我们?

psp*_*psp 26

通过简单地使用JDBC,没有有效的方法.您必须将限制制定为n行,从第i个项子句直接开始到SQL,以使其高效.根据数据库,这实际上可能非常简单(参见MySQL的LIMIT -keyword),在其他数据库(如Oracle)上,它可能有点棘手(涉及子查询和使用rownum伪列).

请参阅此JDBC分页教程:http: //java.avdiel.com/Tutorials/JDBCPaging.html


Bal*_*usC 20

您应该查询实际需要在当前页面上显示的数据.不要将整个数据集拖入Java的内存中,然后在那里过滤它.它只会让事情变得不必要地变慢.

如果您实际上很难正确地实现这个和/或为特定数据库计算SQL查询,那么请在这里查看我的答案 .

更新:既然你正在使用Oracle,这里是上述答案的Oracle目标摘录:

在Oracle中,您需要一个子查询with rownum子句,它应该如下所示:

private static final String SQL_SUBLIST = "SELECT id, username, job, place FROM"
    + " (SELECT id, username, job, place FROM contact ORDER BY id)"
    + " WHERE ROWNUM BETWEEN %d AND %d";

public List<Contact> list(int firstrow, int rowcount) {
    String sql = String.format(SQL_SUBLIST, firstrow, firstrow + rowcount);

    // Implement JDBC.
    return contacts;
}
Run Code Online (Sandbox Code Playgroud)

  • 在DB中保留这些100.000行.查询**仅**您需要**每页显示的那些**.谷歌也不会一次查询那些数量的行,只显示结果页面上的前十行. (3认同)
  • 你必须.它不是ANSI SQL标准的一部分.您还可以为所有五个主要RDBMS供应商编写查询,并添加配置设置或JDBC URL自动检测器,以确定您要打开的数据库供应商特定查询.另一个选择是使用Hibernate/JPA,它已经为您提取了数据库供应商的东西.最后一个选项是在普通Java中完成这项工作.但你真的不想这样做. (3认同)

vin*_*lcy 9

免责声明:这篇关于SQL分页和JDBC分页的博文由我发布.

无视Hibernate分页,我们可以使用SQL分页/ JDBC分页

SQL分页

有两种基本方法:

  1. 在零碎的结果集上运行(每页的新查询)
  2. 在完整的结果集上运行

这样做的方法是SQL特定的

对于MySQL /许多其他SQL,可以使用限制和偏移来完成

Postgresql:http://microjet.ath.cx/WebWiki/ResultPaginationWithPostgresql.html

在Oracle中,它使用与处理"Top-N查询"相同的形式,例如谁是5位最高薪员工,这是优化的

select *   from ( select a.*, rownum rnum

from ( YOUR_QUERY_GOES_HERE -- including the order by ) a

where rownum <= MAX_ROWS )

where rnum >= MIN_ROWS
Run Code Online (Sandbox Code Playgroud)

这是关于ROW-NUM的非常详细的解释

类似SO线程

JDBC分页

我想到的问题是:当我执行SQL时,如何加载结果?是立即还是应要求?和这个SO线程一样

首先,我们需要了解一些JDBC的基础知识,例如Oracle

每个javadoc:statement.execute()

execute: Returns true if the first object that the query returns is a ResultSet object. Use this method if the query could return one or more ResultSet objects. Retrieve the ResultSet objects returned from the query by repeatedly calling Statement.getResutSet.
Run Code Online (Sandbox Code Playgroud)

我们通过游标访问Resultset中的数据.请注意,此光标与DB的光标不同,而它是最初位于第一行数据之前的指针.

根据请求获取数据.当你执行execute()时,你是第一次获取.

那么,加载了多少数据?它是可配置的.可以使用ResultSet上的java API setFetchSize()方法来控制驱动程序每次从DB获取的行数,以及它一次检索的块大小.

例如,假设总结果为1000.如果获取大小为100,则获取第1行将从DB加载100行,第2行将从本地内存加载到第100行.查询第101行将另外100行加载到内存中.

来自JavaDoc

Gives the JDBC driver a hint as to the number of rows that should be fetched from the database when more rows are needed for ResultSet objects genrated by this Statement. If the value specified is zero, then the hint is ignored. The default value is zero.
Run Code Online (Sandbox Code Playgroud)

注意单词"hint" - 它可以通过驱动程序特定的实现来覆盖.

这也是基于SQL开发人员的客户端中的"限制行数为100"的功能.

完成整个解决方案,要滚动结果,需要考虑API中的ResultSet类型和ScrollableCursor

可以从oracle中的这篇文章中找到一个示例实现

它来自Oracle Toplink Developer's Guide Example 112 JDBC Driver Fetch Size

ReadAllQuery query = new ReadAllQuery();

query.setReferenceClass(Employee.class);

query.setSelectionCriteria(new ExpressionBuilder.get("id").greaterThan(100));

// Set the JDBC fetch size

query.setFetchSize(50);

// Configure the query to return results as a ScrollableCursor

query.useScrollableCursor();

// Execute the query

ScrollableCursor cursor = (ScrollableCursor) session.executeQuery(query);

// Iterate over the results

while (cursor.hasNext()) {

System.out.println(cursor.next().toString());

}

cursor.close();
Run Code Online (Sandbox Code Playgroud)

.....................

毕竟,问题沸腾了

哪种分页更好?

注意SQL应该是ORDER by才能在SQL方法中有意义,

否则,可以在下一页中再次显示一些行.

以下是Postgresql关于JDBC驱动程序和其他SO答案的文档中的一些要点

首先,原始查询需要有一个ORDER BY子句才能使寻呼解决方案合理地工作.否则,Oracle为第一页,第二页和第N页返回相同的500行是完全有效的

主要区别在于JDBC方式,在获取期间需要保持连接.例如,这可能不适用于无状态Web应用程序.

对于SQL方式

语法是特定于SQL的,可能不容易维护. 对于JDBC方式

  • 与服务器的连接必须使用V3协议.这是服务器版本7.4及更高版本的默认设置(仅受支持).
  • Connection不能处于自动提交模式.后端在事务结束时关闭游标,因此在自动提交模式下,后端将关闭游标,然后才能从中获取任何内容.
  • 必须使用ResultSet类型ResultSet.TYPE_FORWARD_ONLY创建Statement.这是默认值,因此不需要重写代码以利用此功能,但这也意味着您无法向后滚动或以其他方式在ResultSet中跳转.
  • 给出的查询必须是单个语句,而不是与分号串在一起的多个语句.

一些进一步阅读

这篇文章是关于光学提取大小的性能调整