Java ResultSet, как проверить, есть ли какие-либо результаты


312

Resultset не имеет метода для hasNext. Я хочу проверить, имеет ли значение resultSet какое-либо значение

это правильный путь

if (!resultSet.next() ) {
    System.out.println("no data");
} 

2
Для будущих читателей, таких как я: ответы, которые мне помогли, - это ответы Фелипе и Дермота Доэрти
Бендж

Ответы:


239

Это правильно, изначально ResultSetкурсор указывает на первую строку, если первый вызов next()возвращает, falseто в ResultSet.

Если вы используете этот метод, вам, возможно, придется вызывать его beforeFirst()сразу же после сброса, поскольку теперь он находится за первой строкой.

Следует отметить, однако, что ответ Зайфера ниже является более элегантным решением этого вопроса.


37
Но имейте в виду, если есть / есть / строки, после этого теста вы будете указывать на первый ряд. Поэтому убедитесь, что вы случайно не пропустите строку.
Мэтью Флэшен

1
Хорошо, что курсор (указатель) указывает на первую строку
JohnMerlino

@ MatthewFlaschen, вы правы, чтобы решить проблему пропуска первой строки, я использовал do {...} while (rs.next);
Исраэль

8
Вы также можете просто позвонить, isBeforeFirst()чтобы проверить, есть ли какие-либо строки, возвращаемые без перемещения курсора, а затем продолжить работу в обычном режиме.
SnakeDoc

529

Предполагая, что вы работаете с вновь возвращенным ResultSet, курсор которого направлен перед первой строкой, более простой способ проверить это - просто позвонить isBeforeFirst(). Это исключает необходимость повторного отслеживания, если данные должны быть прочитаны.

Как объяснено в документации , это возвращает false, если курсор находится не перед первой записью, или если в ResultSet нет строк .

if (!resultSet.isBeforeFirst() ) {    
    System.out.println("No data"); 
} 

 


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

5
Обратите внимание, что по крайней мере для DB2 набор результатов должен быть «прокручиваемым». Это может быть установлено при создании оператора для выполнения.
Лоуренс Дугал Майерс


Из документации Oracle: Примечание: поддержка метода isBeforeFirst является необязательной для ResultSets с типом набора результатов TYPE_FORWARD_ONLY
emi-le

52

Вы всегда можете сделать следующий шаг вперед, и просто сделать проверку после цикла

if (!resultSet.next() ) {
    System.out.println("no data");
} else {

    do {
     //statement(s)
    } while (resultSet.next());
}

21

Обычно вы делаете что-то вроде этого:

while ( resultSet.next() ) { 
   // Read the next item
   resultSet.getString("columnName");
}

Если вы хотите сообщить о пустом наборе, добавьте переменную, считающую прочитанные элементы. Если вам нужно прочитать только один элемент, то ваш код адекватен.


16

Чтобы быть полностью уверенным, скорее набор результатов пуст или нет независимо от позиции курсора, я бы сделал что-то вроде этого:

public static boolean isMyResultSetEmpty(ResultSet rs) throws SQLException {
    return (!rs.isBeforeFirst() && rs.getRow() == 0);
}

Эта функция вернет true, если ResultSet пуст, и false, если нет, или выдает SQLException, если этот ResultSet закрыт / неинициализирован.


12

Лучше всего использовать ResultSet.next () вместе с синтаксисом do {...} while () для этого.

Вызов «проверка на любые результаты» ResultSet.next () перемещает курсор в первую строку, поэтому используйте синтаксис do {...} while () для обработки этой строки, продолжая при этом обрабатывать оставшиеся строки, возвращаемые циклом.

Таким образом, вы можете проверить любые результаты, в то же время обрабатывая все возвращенные результаты.

if(resultSet.next()) { // Checks for any results and moves cursor to first row,
    do { // Use 'do...while' to process the first row, while continuing to process remaining rows

    } while (resultSet.next());
}

8

Согласно наиболее жизнеспособному ответу, предлагается использовать isBeforeFirst (). Это не лучшее решение, если у вас нет типа «только вперед» .

Есть метод с именем " .first () ". Это менее излишне, чтобы получить точно такой же результат. Вы проверяете, есть ли что-то в вашем «наборе результатов» и не перемещаете курсор.

В документации говорится: «(...) false, если в наборе результатов нет строк ».

if(rs.first()){
    //do stuff      
}

Вы также можете просто вызвать isBeforeFirst (), чтобы проверить, есть ли какие-либо строки, возвращенные без перемещения курсора, а затем продолжить работу в обычном режиме. - SnakeDoc 2 сентября '14 в 19:00

Однако есть разница между «isBeforeFirst ()» и «first ()». Сначала генерируется исключение, если сделано для набора результатов типа «только вперед».

Сравните два раздела броска: http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#isBeforeFirst () http://docs.oracle.com/javase/7/docs /api/java/sql/ResultSet.html#first ()

Хорошо, в основном это означает, что вы должны использовать «isBeforeFirst», если у вас есть тип «только вперед». В противном случае использовать "first ()" не так уж и сложно.


1
Как "меньше перебор", чтобы получить точно такой же результат? Мне кажется, что цель first () - переместить курсор в первую строку, если ее там еще нет (и вернуть true, если это удалось). isBeforeFirst является чисто диагностической функцией и кажется более подходящей для целей автора. Плюс, способ first () сформулирован, он возвращает true, если он находится «в допустимой строке» ... что странно, поскольку можно подумать, что он будет сформулирован как «в первой строке». Для меня, я не вижу преимущества использования first () в этом сценарии, если ваш курсор не продвинулся и вы не хотите вернуть его в начало.
Jon

5

Это сработало бы, если вы хотите увидеть, есть ли какие-либо строки в результирующем наборе да.

Обратите внимание, что он next()всегда переходит к следующему ряду, поэтому, если вы планируете делать какие-либо чтения из набора результатов, вы должны принять это во внимание.

Обычное использование с ResultSet (при простом чтении):

while (resultSet.next())
{
   ... read from the row here ...
}

Что, очевидно, не будет работать правильно, если вы next()уже вызывали один раз, чтобы проверить, был ли набор результатов пуст, так что следите за этим. Хотя существуют методы для «резервного копирования», они не поддерживаются для всех типов наборов результатов.


5

Это практичная и легко читаемая часть, я верю.

        if (res.next()) {
            do {

                // successfully in. do the right things.

            } while (res.next());
        } else {
           // no results back. warn the user.
        }

2
if (!resultSet.isAfterLast() ) {    
System.out.println("No data"); 
} 

isAfterLast() также возвращает false для пустого набора результатов, но так как курсор в любом случае находится перед первой строкой, этот метод кажется более понятным.


2
if(resultSet.first) {

} else { 
    system.out.println("No raw or resultSet is empty");
}

Потому что, если ResultSet не имеет raw, тогда resultSet.firstвозвращает false.


Но он перемещает курсор на первую строку, ненужный, и это может запутать дальнейшее использование объекта ob «reset» и может привести к потере данных
Тигран Бабаджанян

Хотя это выглядит лучше, оно не будет работать с результирующим набором только вперед.
eliteproxy

1

Лучше всего проверить первую строку, чтобы при попытке получить данные вы могли избежать ошибки пропуска строки. Примерно так: if (! ResultSet.first ()) {System.out.println ("нет данных"); }


1

С помощью resultSet.next () вы можете легко получить результат, независимо от того, содержит ли resultSet какое-либо значение или нет

ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next())
 //resultSet contain some values
else
 // empty resultSet

Не повторяйте существующие ответы.
james.garriss


1

Я пытался установить текущую строку в первый индекс (имеет дело с первичными ключами). Я бы предложил

if(rs.absolute(1)){
    System.out.println("We have data");
} else {
    System.out.println("No data");
}

Когда ResultSet заполнен, он указывает на перед первой строкой. При установке в первую строку (обозначенную rs.absolute(1)) он вернет истину, означающую, что он был успешно помещен в строку 1, или ложь, если строка не существует. Мы можем экстраполировать это на

for(int i=1; rs.absolute(i); i++){
    //Code
}

который устанавливает текущую строку в положение i и потерпит неудачу, если строка не существует. Это просто альтернативный метод

while(rs.next()){
    //Code
}

Какой твой ответ?
CMedina

1

Я создал следующий метод, чтобы проверить, является ли ResultSet пустым.

public static boolean resultSetIsEmpty(ResultSet rs){        
    try {
        // We point the last row
        rs.last();
        int rsRows=rs.getRow(); // get last row number

        if (rsRows == 0) {
            return true;
        }

        // It is necessary to back to top the pointer, so we can see all rows in our ResultSet object.
        rs.beforeFirst();
        return false;
    }catch(SQLException ex){            
        return true;
    }
}

Очень важно иметь следующие соображения:

CallableStatement объект должен быть установлен, чтобы позволить объекту ResultSet идти в конце и вернуться наверх.

TYPE_SCROLL_SENSITIVE : объект ResultSet может сместиться в конце и вернуться наверх. Далее можете отловить последние изменения.

CONCUR_READ_ONLY : мы можем прочитать данные объекта ResultSet, но не можем обновить.

CallableStatement proc = dbconex.prepareCall(select, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);

1

Я думаю, что самый простой способ проверить набор результатов - через CollectionUtils в пакете org.apache.commons.collections.CollectionUtils

if(CollectionUtils.isNotEmpty(resultList)){
  /**
  * do some stuff
  */
}

Это проверит как нулевое, так и пустое условие набора результатов.

Для получения более подробной информации вы можете обратиться к следующему документу. CollectionUtils


1
ResultSet не является коллекцией.
Иоахим Лус

1

Почему бы не использовать rs.getRow ()?

int getRow()
           throws SQLException
Retrieves the current row number. The first row is number 1, the second number 2, and so on.
Note:Support for the getRow method is optional for ResultSets with a result set type of TYPE_FORWARD_ONLY

Returns:
the current row number; 0 if there is no current row
Throws:
SQLException - if a database access error occurs or this method is called on a closed result set
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
Since:
1.2

Для меня проверка "если (rs.getRow ()! = 0)", кажется, работает просто отлично.


0

вы можете сделать что-то вроде этого

boolean found = false;

while ( resultSet.next() )
{
    found = true;
    resultSet.getString("column_name");
}

if (!found)
    System.out.println("No Data");

1
WAAAY слишком сложный.
jordaniac89

0
ResultSet rs = rs.executeQuery();
if(rs.next())
{
  rs = rs.executeQuery();
  while(rs.next())
  {
    //do code part
  }
}
else
{
  //else if no result set
}

Лучше повторно выполнить запрос, потому что при вызове if(rs.next()){....}будет выполнен первый ряд ResultSet, а после него while(rs.next()){....}мы получим результат из следующей строки. Поэтому я думаю, что повторное выполнение запроса внутри ifявляется лучшим вариантом.


5
-1 Это не лучший вариант. Зачем запрашивать базу данных дважды? Что если данные резко меняются между вызовами? Это расточительно.
Тоби Колк

-2

Первоначально объект набора результатов (rs) указывает на BFR (до первой записи). Как только мы используем rs.next (), курсор указывает на первую запись, а rs содержит «true». Используя цикл while, вы можете распечатать все записи таблицы. После того, как все записи получены, курсор перемещается в ALR (после последней записи), и он будет установлен в ноль. Давайте рассмотрим, что в таблице 2 записи.

if(rs.next()==false){
    // there are no records found
    }    

while (rs.next()==true){
    // print all the records of the table
    }

Вкратце, мы также можем записать условие как while (rs.next ()).


3
Ваш цикл while не сможет работать с первым возвращенным рядом, что кажется несколько фатальным недостатком при таком подходе. Есть много предложений, которые лучше, чем этот.
Жюль
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.