Отказ от ответственности: Этот пост в блоге о разбиении на страницы SQL и JDBC размещен мной.
Независимо от нумерации страниц Hibernate, мы можем использовать нумерацию страниц SQL / пагинацию JDBC
SQL-нумерация страниц
Существует два основных подхода:
- работа с частичным набором результатов (новый запрос для каждой страницы)
- работает с полным набором результатов
Способ сделать это зависит от SQL
Для MySQL / многих других SQL это можно сделать с помощью limit и offset
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
Вот очень подробное объяснение ROW-NUM
Аналогично SO Thread
JDBC Pagination
Возникает вопрос: когда я выполняю SQL, как загружается результат? Сразу или по запросу? так же, как эта тема
Сначала нам нужно понять некоторые основы 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.
Доступ к данным в Resultset осуществляется с помощью курсора. Обратите внимание, что этот курсор отличается от курсора в DB, в то время как он является указателем, первоначально расположенным перед первой строкой данных.
Данные извлекаются по запросу. в то время как при выполнении execute () вы выбираете в первый раз.
Тогда сколько данных загружено? Это настраивается.
Можно использовать метод java API setFetchSize () в ResultSet, чтобы контролировать, сколько строк извлекается драйвером из БД за раз, насколько большие блоки он получает одновременно.
Например, предположим, что суммарный результат равен 1000. Если размер выборки равен 100, выборка 1-й строки загрузит 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.
Обратите внимание на слово «подсказка» - оно может быть переопределено конкретной реализацией драйвера.
Это также то, на чем основывается функция «Ограничение строк до 100» в клиенте, например, для разработчика SQL.
Завершая все решение, для прокрутки результатов необходимо учитывать типы ResultSet и ScrollableCursor в API
Пример реализации из этого поста можно найти в oracle
из книги Oracle Toplink: Руководство разработчика
Пример 112 Размер выборки драйвера JDBC
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();
.....................
В конце концов, вопросы сводятся к
Какой лучший способ сделать нумерацию страниц?
Обратите внимание, что SQL должен быть ORDER, чтобы иметь смысл в подходе SQL,
В противном случае на следующей странице можно снова показать несколько строк.
Ниже приведены некоторые пункты из документации Postgresql по драйверу JDBC и другие ответы SO
Во-первых, исходный запрос должен иметь предложение ORDER BY, чтобы обеспечить разумную работу решения для пейджинга. В противном случае было бы совершенно правильным, чтобы Oracle возвращал те же 500 строк для первой страницы, второй страницы и N-й страницы
Основное отличие заключается в способе JDBC, который требуется для удержания соединения во время выборки. Это может быть неприемлемо, например, в веб-приложении без сохранения состояния.
Для SQL-пути
синтаксис специфичен для SQL и может быть нелегко поддерживать.
Для JDBC way
- Соединение с сервером должно осуществляться по протоколу V3. Это
по умолчанию для (и поддерживается только) версий сервера 7.4 и
потом.
- Соединение не должно быть в режиме автоматической фиксации. Бэкэнд
закрывает курсоры в конце транзакции, поэтому в режиме автоматической фиксации
бэкэнд закроет курсор, прежде чем что-либо может быть получено
из него.
- Оператор должен быть создан с типом ResultSet
ResultSet.TYPE_FORWARD_ONLY. Это значение по умолчанию, поэтому код не будетнужно переписать, чтобы воспользоваться этим, но это также означает,
что вы не можете прокрутить назад или иначе прыгать в
ResultSet.
- Данный запрос должен быть одним оператором, а не множественным
утверждения, соединенные точкой с запятой.
Некоторое дальнейшее чтение
Этот пост о настройке производительности с оптическим размером выборки