← Назад к вопросам

Существует ли текущий элемент при начале работы с ResultSet

1.3 Junior🔥 181 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Существует ли текущий элемент при начале работы с ResultSet

Нет, при начале работы с ResultSet текущего элемента не существует. Курсор находится в позиции перед первой строкой (before the first row).

Структура курсора в ResultSet

┌─ Before first row (начальная позиция) — Курсор здесь!
├─ Row 1
├─ Row 2
├─ Row 3
└─ After last row

Опокупатель cursor находится в позиции 0, а первый ряд находится в позиции 1.

Получение данных из ResultSet

Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");

// Позиция курсора: ДО первой строки (before first row)
// rs.getInt("id") вызовет исключение!

// Нужно СНАЧАЛА переместиться на строку
while (rs.next()) {  // next() возвращает true, если есть строка
    // Теперь текущая позиция — первая/следующая строка
    int id = rs.getInt("id");      // OK
    String name = rs.getString("name");  // OK
    System.out.println(id + ": " + name);
}

// После цикла курсор находится после последней строки

Методы навигации по ResultSet

ResultSet rs = statement.executeQuery(...);

// Перемещение вперёд
boolean hasNext = rs.next();  // На следующую строку
boolean first = rs.first();   // На первую строку
boolean last = rs.last();     // На последнюю строку
boolean absolute = rs.absolute(3);  // На абсолютную позицию (3-я строка)
boolean relative = rs.relative(2);  // На 2 строки вперёд от текущей

// Проверка позиции
boolean isFirst = rs.isFirst();
boolean isLast = rs.isLast();
boolean beforeFirst = rs.isBeforeFirst();
boolean afterLast = rs.isAfterLast();

// Получение номера строки
int row = rs.getRow();  // Текущий номер строки (1-based index)

Практические примеры

Пример 1: Правильное использование next()

String sql = "SELECT id, name FROM users";
ResultSet rs = stmt.executeQuery(sql);

// ✅ Правильно
while (rs.next()) {
    // rs.next() возвращает true, если есть строка
    // и перемещает курсор НА эту строку
    int id = rs.getInt("id");
    String name = rs.getString("name");
}

// ❌ Неправильно
while (rs.getRow() <= rs.getFetchSize()) {
    // Курсор не в начальной позиции
}

Пример 2: Обработка результатов

Statement stmt = connection.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE,  // Можем прыгать
    ResultSet.CONCUR_READ_ONLY          // Только читаем
);
ResultSet rs = stmt.executeQuery("SELECT * FROM products");

// Курсор: перед первой строкой
if (rs.first()) {
    // Теперь на первой строке
    System.out.println(rs.getString("name"));
}

// Перейти на последнюю строку
if (rs.last()) {
    System.out.println(rs.getRow());  // Номер последней строки
}

// Перейти на конкретную строку
if (rs.absolute(5)) {  // 5-я строка (1-based)
    System.out.println(rs.getString("name"));
} else {
    System.out.println("Строка 5 не существует");
}

Пример 3: Проверка наличия строк

ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE id = 999");

// ✅ Правильно: проверяем, есть ли хотя бы одна строка
if (rs.next()) {
    int id = rs.getInt("id");
    System.out.println("Found: " + id);
} else {
    System.out.println("No user found");
}

Типы ResultSet

Вид поведения курсора зависит от типа ResultSet:

// TYPE_FORWARD_ONLY (по умолчанию)
Statement stmt1 = conn.createStatement(
    ResultSet.TYPE_FORWARD_ONLY,      // Только next()
    ResultSet.CONCUR_READ_ONLY
);
// Можно использовать: next(), getRow()
// Нельзя: previous(), last(), absolute()

// TYPE_SCROLL_INSENSITIVE
Statement stmt2 = conn.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE,  // Можем прыгать
    ResultSet.CONCUR_READ_ONLY
);
// Можно использовать: все методы навигации
// Но потребляет больше памяти

// TYPE_SCROLL_SENSITIVE (редко)
Statement stmt3 = conn.createStatement(
    ResultSet.TYPE_SCROLL_SENSITIVE,   // Видим обновления других сессий
    ResultSet.CONCUR_READ_ONLY
);

Частые ошибки

// ❌ Ошибка 1: Нет next()
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
int id = rs.getInt("id");  // SQLException!

// ✅ Исправление
if (rs.next()) {
    int id = rs.getInt("id");  // OK
}

// ❌ Ошибка 2: Забыл про позицию курсора
rs.last();  // На последнюю строку
rs.next();  // Ничего не происходит, курсор после последней строки
if (rs.next()) {
    // Это никогда не выполнится
}

// ✅ Исправление
rs.beforeFirst();  // Сбрасываем на начало
while (rs.next()) {
    // Теперь правильно
}

Механизм работы next()

public boolean next() throws SQLException {
    // 1. Если курсор перед первой строкой
    //    → переместить на первую строку, вернуть true
    // 2. Если курсор на строке
    //    → переместить на следующую строку, вернуть true
    // 3. Если нет больше строк
    //    → вернуть false, курсор остаётся после последней
}

Best Practices

  1. Всегда вызывай next() перед доступом к данным
if (rs.next()) {
    // Безопасный доступ к данным
}
  1. Используй try-with-resources для автоматического закрытия
try (Statement stmt = conn.createStatement();
     ResultSet rs = stmt.executeQuery(sql)) {
    while (rs.next()) {
        // Работа с данными
    }
}  // Автоматически закроется
  1. Проверяй существование строк при SELECT по ID
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, userId);
ResultSet rs = pstmt.executeQuery();

if (rs.next()) {
    User user = mapRowToUser(rs);
    return user;
} else {
    throw new UserNotFoundException("User not found");
}

Итог

Нет, при начале работы с ResultSet текущего элемента не существует. Курсор находится перед первой строкой (before first row). Нужно вызвать next() или другой метод навигации, чтобы переместить курсор на конкретную строку и получить доступ к данным.

Существует ли текущий элемент при начале работы с ResultSet | PrepBro