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

Как называется сущность, которая обладает информацией о следующем элементе в ResultSet

1.0 Junior🔥 61 комментариев
#Другое

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

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

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

# Cursor в ResultSet

Что такое Cursor?

Cursor (курсор) — это сущность в JDBC, которая обладает информацией о текущей позиции и может перемещаться по результатам запроса в ResultSet. Курсор указывает на строку данных и позволяет перемещаться между строками.

Работа с Cursor через ResultSet

import java.sql.*;

public class CursorExample {
    public static void main(String[] args) {
        String query = "SELECT id, name, email FROM users";
        
        try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password");
             Statement statement = conn.createStatement();
             ResultSet resultSet = statement.executeQuery(query)) {
            
            // Cursor находится ПЕРЕД первой строкой
            while (resultSet.next()) {  // next() движет cursor на следующую строку
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                String email = resultSet.getString("email");
                
                System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
            }
            // После цикла cursor находится ПОСЛЕ последней строки
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Методы перемещения Cursor

Основные методы навигации:

resultSet.next();          // Движет cursor на следующую строку
resultSet.previous();       // Движет cursor на предыдущую строку (для прокручиваемых)
resultSet.first();          // Переместиться на первую строку
resultSet.last();           // Переместиться на последнюю строку
resultSet.beforeFirst();    // Переместиться ПЕРЕД первую строку
resultSet.afterLast();      // Переместиться ПОСЛЕ последнюю строку
resultSet.absolute(n);      // Переместиться на n-ую строку (1-indexed)
resultSet.relative(n);      // Переместиться на n позиций относительно текущей

Пример использования методов навигации

import java.sql.*;

public class CursorNavigation {
    public static void main(String[] args) {
        String query = "SELECT id, name FROM users";
        
        try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "pass");
             Statement statement = conn.createStatement(
                 ResultSet.TYPE_SCROLL_INSENSITIVE,  // Прокручиваемый ResultSet
                 ResultSet.CONCUR_READ_ONLY
             );
             ResultSet rs = statement.executeQuery(query)) {
            
            // Переместиться на последнюю строку
            rs.last();
            int lastRow = rs.getRow();
            System.out.println("Total rows: " + lastRow);
            
            // Переместиться на первую строку
            rs.first();
            System.out.println("First user: " + rs.getString("name"));
            
            // Переместиться на 3-ю строку
            rs.absolute(3);
            System.out.println("Third user: " + rs.getString("name"));
            
            // Переместиться на 2 позиции вперёд
            rs.relative(2);
            System.out.println("User at +2: " + rs.getString("name"));
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Типы ResultSet

Тип ResultSet определяет, является ли он прокручиваемым:

// TYPE_FORWARD_ONLY - только вперёд (по умолчанию)
Statement stmt = connection.createStatement(
    ResultSet.TYPE_FORWARD_ONLY,
    ResultSet.CONCUR_READ_ONLY
);

// TYPE_SCROLL_INSENSITIVE - прокручиваемый, не видит изменения
Statement stmt = connection.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE,
    ResultSet.CONCUR_READ_ONLY
);

// TYPE_SCROLL_SENSITIVE - прокручиваемый, видит изменения
Statement stmt = connection.createStatement(
    ResultSet.TYPE_SCROLL_SENSITIVE,
    ResultSet.CONCUR_UPDATABLE
);

Методы получения информации о Cursor

import java.sql.*;

public class CursorInfo {
    public static void main(String[] args) {
        String query = "SELECT id, name FROM users";
        
        try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "pass");
             Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
             ResultSet rs = statement.executeQuery(query)) {
            
            // Информация о текущей позиции cursor
            rs.next();
            
            int currentRow = rs.getRow();  // Номер текущей строки
            boolean isFirst = rs.isFirst();  // Курсор на первой строке?
            boolean isLast = rs.isLast();    // Курсор на последней строке?
            boolean isBeforeFirst = rs.isBeforeFirst();  // Курсор перед первой строкой?
            boolean isAfterLast = rs.isAfterLast();      // Курсор после последней строки?
            
            System.out.println("Current row: " + currentRow);
            System.out.println("Is first: " + isFirst);
            System.out.println("Is last: " + isLast);
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Практический пример: Работа с Cursor

import java.sql.*;

public class CursorPractical {
    
    public void iterateTwice(ResultSet rs) throws SQLException {
        // Итерация вперёд
        System.out.println("=== Forward iteration ===");
        rs.beforeFirst();
        while (rs.next()) {
            System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
        }
        
        // Итерация назад
        System.out.println("=== Backward iteration ===");
        while (rs.previous()) {
            System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
        }
    }
    
    public void getNextElement(ResultSet rs) throws SQLException {
        // Проверяем, есть ли следующий элемент
        if (rs.next()) {
            String nextElement = rs.getString("name");
            System.out.println("Next element: " + nextElement);
            
            // Возвращаемся на шаг назад для продолжения итерации
            rs.previous();
        }
    }
}

Сравнение Cursor в разных БД

БДТипПоддержка
MySQLJDBC ResultSetПрокручиваемые, но требуют TYPE_SCROLL_INSENSITIVE
PostgreSQLJDBC ResultSetПолная поддержка курсоров
OracleJDBC ResultSet + CursorРасширенная поддержка
SQL ServerJDBC ResultSetПолная поддержка прокручиваемых

Производительность

// ❌ НЕЭФФЕКТИВНО - пересчёт для каждого доступа
for (int i = 1; i <= totalRows; i++) {
    rs.absolute(i);
    process(rs);
}

// ✅ ЭФФЕКТИВНО - один проход
rs.beforeFirst();
while (rs.next()) {
    process(rs);
}

Важные замечания

  1. Cursor начинает позицию ПЕРЕД первой строкой — нужно вызвать next()
  2. TYPE_FORWARD_ONLY быстрее — используй, если не нужна прокрутка
  3. Работай с курсором в try-with-resources — для автоматического закрытия
  4. Проверяй hasNext() перед next() — избегай исключений

Вывод: Cursor в ResultSet — это механизм JDBC для навигации по результатам запроса. Основной метод — next(), который движет курсор на следующую строку. Для полной навигации используй TYPE_SCROLL_INSENSITIVE или TYPE_SCROLL_SENSITIVE.