Всего строк JDBC ResultSet

Я реализую пейджинг в своем приложении. Для этого я запускаю запрос и получаю ResultSet.
Теперь я хочу получить общее количество записей в этом ResultSet для расчета подкачки.
Как я могу это получить? Я не хочу выполнять дополнительный SQL, который дает мне общее количество строк.


person Zeeshan    schedule 14.06.2010    source источник
comment
Просто интересно, это веб-приложение? Если мы не говорим о 1000+ записях из запроса, вы можете очень легко реализовать разбиение на страницы с помощью java-скрипта и избежать необходимости обращаться к серверу для каждой страницы.   -  person CoolBeans    schedule 15.06.2010


Ответы (7)


Другой вариант — добавить агрегацию счетчика в качестве подзапрошенного столбца в ваш запрос. Если ваша база данных немного умнее, она выполнит это только один раз. Вы должны быть в состоянии легко проверить это, используя анализатор запросов в вашей любимой базе данных.

SELECT id,username,(SELECT COUNT(id) FROM users) FROM users;
person kasperjj    schedule 14.06.2010
comment
я рекомендовал использовать решение Java, потому что если у нас есть сложный запрос, это будет иметь стоимость производительности - person Fareed Alnamrouti; 08.01.2013
comment
Если вы не используете базу данных с очень примитивным оптимизатором запросов, подсчет количества строк в результирующем наборе будет не более затратным, чем выполнение этого позже на стороне Java. - person kasperjj; 24.10.2013

Обычная практика состоит в том, чтобы сопоставить ResultSet с List<Entity>, где Entity – это объект javabean, представляющий фактические данные, например User, Product, Order и т. д.

Затем вы можете просто использовать List методы, такие как List#size() для получения количества строк.

List<Entity> entities = entityDAO.list();
int rows = entities.size();

if (entities.isEmpty()) {
    // It is empty!
} else if (entities.size() == 1) {
    // It has only one row!
} else {
    // It has more than one row!
}
person BalusC    schedule 14.06.2010
comment
Спасибо за ваш ответ. На самом деле я не хочу получать все строки в коллекции, потому что я хочу отображать только 10 строк на странице, поэтому мой расчет подкачки помогает мне получить только 10 строк из набора результатов. Для этого мне нужно общее количество строк в наборе результатов. - person Zeeshan; 14.06.2010
comment
Затем выполните два запроса: один для получения COUNT(*) (или лучше COUNT(pk)) и другой для получения интересующих строк. Хотя это, вероятно, не полностью соответствует вашим требованиям (веб-приложение JSF), вы можете получить некоторую полезную информацию из этой статьи. - person BalusC; 15.06.2010

Если я не ошибаюсь, поведение по умолчанию для ResultSet заключается в том, чтобы не получать все строки сразу, поэтому из самого объекта невозможно узнать, сколько строк будет возвращено из запроса без предварительной итерации (и, следовательно, получения ) все они. Вы можете получить другое поведение с определенными драйверами JDBC для определенных баз данных.

Могу я спросить, почему вам слишком дорого сначала запускать запрос COUNT()? По сравнению со стоимостью получения фактических значений это не должно быть слишком дорого.

person Uri    schedule 14.06.2010
comment
это лучшая практика, чтобы запустить запрос для подсчета? Там в любом случае ? - person Zeeshan; 14.06.2010
comment
Я не знаю, является ли это лучшей практикой, но если вы сначала запустите запрос на подсчет (например, SELECT COUNT(*) as NumExpectedRows FROM table WHERE what;), вы можете предсказать количество строк, которые вы получите из набора результатов без построение всего комплекса. Базы данных должны оптимизировать это (проверьте документацию конкретного поставщика). Предостережение заключается в том, что количество строк не должно меняться, пока вы не выполните настоящий запрос. - person Uri; 14.06.2010
comment
да, количество может меняться между двумя запросами, поэтому оно может быть неточным. Но в этом приложении счетчик также может меняться между временем, когда пользователь запрашивает страницу 1 и страницу 2, поэтому мы все равно не можем гарантировать идеальную точность. - person Mike Baranczak; 15.06.2010

Из комментария к ответу BalusC:

[...] На самом деле я не хочу получать все строки в коллекции, потому что я хочу отображать только 10 строк на странице, поэтому мой расчет подкачки помогает мне получить только 10 строк из набора результатов. Для этого мне нужно общее количество строк в наборе результатов

Вам не нужно ничего, кроме как запросить у базы данных около 10 строк и размер таблицы. так что у вас фактически есть два (2) вопроса к вашему хранилищу данных, что равно двум (2) запросам на выбор. Сделайте это, как предложил Uri, и не заботьтесь о "наилучшей практике". Если однажды кто-то предложит лучшую практику, вы все равно сможете решить, адаптировать свой код или нет.

person Andreas Dolk    schedule 14.06.2010

Нет смысла подсчитывать размер списка, чтобы получить количество записей, поскольку мы реализуем разбиение на страницы и НЕ ДОЛЖНЫ загружать весь набор результатов за раз.

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

Пример: выберите * из Emp, где rownum>=:beginRecord и rownum‹=:endRecord

***** Логика останется прежней, но синтаксис может измениться в зависимости от типа базы данных. Нужно использовать вложенный запрос, если нам нужно упорядочить любой столбец. *

Я считаю, что count(*) - дорогая операция, скорее я предпочитаю разбиение.

Выберите Eno, Ename , (выберите count() из emp) в качестве record_count из Emp -- Expensive Выберите Eno, Ename , count() over (partition by eno) в качестве record_count из Emp -- Предпочтительный.

***** Разделение по синтаксису может меняться в зависимости от типа базы данных.*

Я рассмотрел базу данных Oracle.

person Lokesh    schedule 21.06.2012

в дополнение к решению Fathah вы можете использовать этот код, также обратите внимание, что, поскольку это указатель памяти, это решение не имеет проблем с производительностью:

int totalRows = 0;
if(rowSet.last()) {
   totalRows = rowSet.getRow();
}
rowSet.beforeFirst();
person Fareed Alnamrouti    schedule 08.01.2013

person    schedule
comment
Вызов resultSet.getRow() напрямую возвращает мне 0. Теперь я вижу, что это означает, сколько строк от текущего местоположения набора результатов до начала. Я блуждаю, почему это разработано так. - person Diluka W; 18.12.2015