Разбиение на страницы JDBC

Я хочу реализовать разбиение на страницы с помощью JDBC. Фактическая вещь, которую я хочу знать, "Как я могу стать первым 50 и затем следующие 50 записей от базы данных для страницы 1 и 2 соответственно"

Мой Запрос Select * from data [таблица данных содержит 20 000 строк]

Для страницы № 1 я получаю 50 записей, и для страницы № 2 я хочу стать следующим 50 записей. Как я могу реализовать его эффективно в JDBC?

Я искал и нашел это rs.absolute(row) путь состоит в том, чтобы пропустить первые записи страницы, но требуется некоторое количество времени на больших наборах результатов, и я не хочу переносить это количество времени. Кроме того, я не хочу использовать rownum и limit + offset в запросе, потому что они не хороши для использования в запросе, я не знаю, почему, тем не менее я не хочу использовать его в запросе.

Может любой помогать мне, как быть ограниченным ResultSet для разбиения на страницы или там какой-либо способ, которым JDBC дает нам?

33
задан BalusC 5 May 2010 в 11:52
поделиться

8 ответов

Нет эффективного способа сделать это простым использованием JDBC. Вы должны сформулировать ограничение до n строк и , начинающихся с предложений i-го элемента непосредственно в SQL, чтобы он был эффективным. В зависимости от базы данных это может быть довольно просто (см. MySQL-ключевое слово LIMIT), в других базах данных, таких как Oracle, это может быть немного сложнее (включает подзапрос и использование псевдоколонки rownum).

См. Это руководство по разбивке на страницы JDBC: http://java.avdiel.com/Tutorials/JDBCPaging.html

26
ответ дан 27 November 2019 в 18:09
поделиться

Если вы используете MySQL или PostgreSQL, ключевыми словами являются limit и offset . MSSqlServer и Oracle имеют схожие функции, но мне это кажется немного более болезненным.

Для MySQL и PostgreSQL см. Здесь:

http://www.petefreitag.com/item/451.cfm

Для Oracle посмотрите здесь:

http://www.oracle-base.com/forums/viewtopic.php?f=2&t=8635

2
ответ дан 27 November 2019 в 18:09
поделиться

Я понимаю, что вы не хотите, чтобы соединение JDBC имело один гигантский набор результатов, который вы держите открытым в течение очень долгого времени и переходите к нему по мере необходимости.

Обычный подход заключается в добавлении SQL, необходимого для получения только подмножества полного запроса, который, к сожалению, отличается от базы данных к базе данных, и сделает ваши SQL-запросы специфичными для конкретного поставщика. Если я правильно помню, LIMIT используется в MySQL. Запрашивайте соответствующий диапазон для каждого запроса.

Я также полагаю, что Hibernate содержит функциональность, которая позволяет делать это для HQL, но я с ней не знаком.

1
ответ дан 27 November 2019 в 18:09
поделиться

Используете ли вы какую-то ORM Framework, например спящий режим, или даже Java Persistence API, или просто SQL?

Тогда мой ответ: используйте LIMIT и OFFSET http://www.petefreitag.com/item/451.cfm

Или используйте оператор ROWNUM Тогда вам понадобится оболочка вокруг вашего SQL, но в основном это

  select * from (select bla.*, ROWNUM rn from (
  <your sql here>
  ) bla where rownum < 200) where rn >= 150'
1
ответ дан 27 November 2019 в 18:09
поделиться

Вы должны запрашивать только данные, которые вам на самом деле нужны для отображения на текущей странице. Не переносите весь набор данных в память Java, а затем фильтруйте его там. Это только сделало бы работу излишне медленнее.

Если вам действительно сложно реализовать это должным образом и / или вычислить SQL-запрос для конкретной базы данных, посмотрите мой ответ здесь .

Обновление: , поскольку вы используете Oracle, вот отрывок из вышеупомянутого ответа, ориентированный на Oracle:

В Oracle вам нужен подзапрос с предложением 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  list (int firstrow, int rowcount) {
String sql = String.format (SQL_SUBLIST, firstrow, firstrow + rowcount); 
 
 // Реализуйте JDBC. 
return contacts; 
} 
 
20
ответ дан 27 November 2019 в 18:09
поделиться

Oracle поддерживает стандартную оконную функцию ROW_NUMBER() начиная с версии 8i, поэтому вы можете использовать ее. Вы можете сделать это как параметризованный запрос, так что вам просто нужно задать начальный и конечный номера строк. Например,

SELECT * 
   FROM ( SELECT *, ROW_NUMBER() ORDER BY (sort key) AS rowNumber FROM <your table name> ) AS data
WHERE 
   rowNumber>=:start AND
   rowNumber<:end

(Если вы не используете именованные параметры, замените :start/:end на позиционный параметр '?')

См. статью SELECT SQL, оконные функции в Википедии. В статье также перечислены другие БД, поддерживающие стандартную оконную функцию ROW_NUMBER().

1
ответ дан 27 November 2019 в 18:09
поделиться
PreparedStatement pStmt = // ... however you make it
pStmt.setFetchSize( /* desired number of records to get into memory */ ); 

Обратите внимание, setFetchSize(int) является лишь подсказкой - в последний раз, когда я использовал его, например, с MySQL, он не поддерживался. Бегло просмотрев документацию Oracle, похоже, что их JDBC поддерживает это. Я бы не стал меня цитировать, но стоит хотя бы попробовать; и да, этот ответ хрупок, но это может быть достаточно меньшей головной болью, чем реализация надежного решения.

По сути, вы можете выдать запрос на все, и за один раз вы получаете в память только размер выборки (при условии, что вы не удерживаете предыдущие результаты). Таким образом, вы устанавливаете размер выборки в 50, делаете подключение/запрос, выводите первые 50 результатов (вызывая еще одну выборку для следующего фрагмента запроса) и т.д.

1
ответ дан 27 November 2019 в 18:09
поделиться

Это ссылка на решение hibernate для постраничного вывода результатов: HQL - идентификатор строки для пагинации

2
ответ дан 27 November 2019 в 18:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: