I want to implement pagination using JDBC. The actual thing I want to know is "How can i get first 50 and then next 50 records from database for page 1 and 2 respectively"
My Query is Select * from data
[data table contains 20,000 rows]
For page #1 I get 50 records and for page #2 I want to get next 50 records. How can I implement it efficiently in JDBC?
I have searched and found that rs.absolute(row)
is the way to skip first page records but it takes some amount of time on large result sets and I don't want to bear this amount of time. Also, I don't want to use rownum
and limit
+ offset
in query because these are not good to use in query, I dont know why, still I don't want to use it in query.
Can anyone help me how to get limited ResultSet
for pagination or is there any way JDBC is giving us?
There is no efficient way of doing this by simply using JDBC. You have to formulate the limit to n rows and start from i-th item clauses directly to the SQL for it to be efficient. Depending on the database this might actually be quite easy (see MySQL's LIMIT -keyword), on other databases such as Oracle it can be a little trickier (involves subquery and using rownum pseudo column).
See this JDBC Pagination Tutorial: http://java.avdiel.com/Tutorials/JDBCPaging.html
You should query only the data you actually need to display on the current page. Do not haul the entire dataset into Java's memory and then filter it there. It would only make things unnecessarily slower.
If you actually have a hard time in implementing this properly and/or figuring the SQL query for the specific database, then have a look at my answer here.
Update: since you're using Oracle, here's an Oracle-targeted extract from the aforementioned answer:
In Oracle you need a subquery with
rownum
clause which should look like: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; }
Disclaimer: This blog post on SQL pagination & JDBC pagination is posted by me.
Disregarding Hibernate pagination, we can use SQL pagination / JDBC pagination
SQL pagination
There are two basic approaches:
The way to do it is SQL specific
For MySQL / many other SQLs it can be done with limit and offset
Postgresql: http://microjet.ath.cx/WebWiki/ResultPaginationWithPostgresql.html
In Oracle, it use the same form as to handle "Top-N query" e.g. who are the 5 highest paid employee, which is optimized
select * from ( select a.*, rownum rnum
from ( YOUR_QUERY_GOES_HERE -- including the order by ) a
where rownum <= MAX_ROWS )
where rnum >= MIN_ROWS
Here is a very detailed explanation on ROW-NUM
Similar SO Thread
JDBC Pagination
The question comes into mind is: when I execute the SQL, how is the result being loaded? Immediately or on request? same as this SO thread
First we need to understand some basics of JDBC, as from Oracle
Per 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.
We access data in Resultset via a cursor. Note this cursor is different from that of DB while it is a pointer initially positioned before the first row of data.
The data is fetch on request. while when you do the execute() you are fetching for the first time.
Then, how many data is loaded? It is configurable. One can use the java API setFetchSize() method on ResultSet to control how many rows are fetched from DB a time by the driver, how big the blocks it retrieves at once.
For example assume the total result is 1000. If fetch size is 100, fetching the 1st row will load 100 rows from DB and 2nd to 100th row will be loaded from local memory.to query 101st row another 100 rows will be load into memory.
From 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.
Note the word "hint" - it can be override by driver specific implementation.
This is also what the "Limit Rows to 100" feature in client like SQL developer based on.
Completing the whole solution, to scroll results, one need to consider the ResultSet Types and ScrollableCursor in API
One can find an example implementation from this post in oracle
which is from the book 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();
.....................
After all, the questions boil to
Which is the better way to do pagination?
Note the SQL should be ORDER by to make sense in the SQL approach,
Otherwise it is possible to show some rows again in next page.
Below is some points from Postgresql's documentation on JDBC Driver and other SO answers
First off, the original query would need to have an ORDER BY clause in order to make the paging solution work reasonably. Otherwise, it would be perfectly valid for Oracle to return the same 500 rows for the first page, the second page, and the Nth page
The major difference is for the JDBC way, it is required to hold the connection during the fetching. This may not be suitable in stateless web application, for example.
For SQL way
the syntax is SQL specific and may not be easy to maintain. For JDBC way
Some Further reading
This post is about performance tuning with optical fetch size
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With