Я хочу реализовать разбиение на страницы с помощью JDBC. Фактическая вещь, которую я хочу знать, "Как я могу стать первым 50 и затем следующие 50 записей от базы данных для страницы 1 и 2 соответственно"
Мой Запрос Select * from data
[таблица данных содержит 20 000 строк]
Для страницы № 1 я получаю 50 записей, и для страницы № 2 я хочу стать следующим 50 записей. Как я могу реализовать его эффективно в JDBC?
Я искал и нашел это rs.absolute(row)
путь состоит в том, чтобы пропустить первые записи страницы, но требуется некоторое количество времени на больших наборах результатов, и я не хочу переносить это количество времени. Кроме того, я не хочу использовать rownum
и limit
+ offset
в запросе, потому что они не хороши для использования в запросе, я не знаю, почему, тем не менее я не хочу использовать его в запросе.
Может любой помогать мне, как быть ограниченным ResultSet
для разбиения на страницы или там какой-либо способ, которым JDBC дает нам?
Нет эффективного способа сделать это простым использованием JDBC. Вы должны сформулировать ограничение до n строк и , начинающихся с предложений i-го элемента непосредственно в SQL, чтобы он был эффективным. В зависимости от базы данных это может быть довольно просто (см. MySQL-ключевое слово LIMIT), в других базах данных, таких как Oracle, это может быть немного сложнее (включает подзапрос и использование псевдоколонки rownum).
См. Это руководство по разбивке на страницы JDBC: http://java.avdiel.com/Tutorials/JDBCPaging.html
Если вы используете MySQL или PostgreSQL, ключевыми словами являются limit и offset . MSSqlServer и Oracle имеют схожие функции, но мне это кажется немного более болезненным.
Для MySQL и PostgreSQL см. Здесь:
http://www.petefreitag.com/item/451.cfm
Для Oracle посмотрите здесь:
Я понимаю, что вы не хотите, чтобы соединение JDBC имело один гигантский набор результатов, который вы держите открытым в течение очень долгого времени и переходите к нему по мере необходимости.
Обычный подход заключается в добавлении SQL, необходимого для получения только подмножества полного запроса, который, к сожалению, отличается от базы данных к базе данных, и сделает ваши SQL-запросы специфичными для конкретного поставщика. Если я правильно помню, LIMIT используется в MySQL. Запрашивайте соответствующий диапазон для каждого запроса.
Я также полагаю, что Hibernate содержит функциональность, которая позволяет делать это для HQL, но я с ней не знаком.
Используете ли вы какую-то 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'
Вы должны запрашивать только данные, которые вам на самом деле нужны для отображения на текущей странице. Не переносите весь набор данных в память 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; }
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().
PreparedStatement pStmt = // ... however you make it
pStmt.setFetchSize( /* desired number of records to get into memory */ );
Обратите внимание, setFetchSize(int)
является лишь подсказкой - в последний раз, когда я использовал его, например, с MySQL, он не поддерживался. Бегло просмотрев документацию Oracle, похоже, что их JDBC поддерживает это. Я бы не стал меня цитировать, но стоит хотя бы попробовать; и да, этот ответ хрупок, но это может быть достаточно меньшей головной болью, чем реализация надежного решения.
По сути, вы можете выдать запрос на все, и за один раз вы получаете в память только размер выборки (при условии, что вы не удерживаете предыдущие результаты). Таким образом, вы устанавливаете размер выборки в 50, делаете подключение/запрос, выводите первые 50 результатов (вызывая еще одну выборку для следующего фрагмента запроса) и т.д.
Это ссылка на решение hibernate для постраничного вывода результатов: HQL - идентификатор строки для пагинации