JavaRush/Курсы/Модуль 4. Работа с БД/Получаем данные из ResultSet

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

Открыта

Управление текущей строкой

Первую программу мы написали и она отлично отработала. Мы написали запрос, выполнили его, и в результате метод executeQuery() вернул нам объект ResultSet, который содержит все результаты запроса. И теперь мы попробуем разобраться, как эти результаты из него получить.

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

Но начнем мы с самого простого — с понятия “текущей строки результата”. Так как строк у результата обычно очень много, то объект ResultSet имеет у себя внутри указатель на текущую строку. И последовательно переключает строки для их чтения с помощью метода next().

Такой подход в первую очередь сделан для оптимизации. JDBC Driver может не загружать строки из базы, пока ты последовательно не дойдешь до их чтения. FileInputStream ты тоже читаешь последовательно с начала и до конца. Так что такой подход должен быть тебе знаком и понятен.

Однако же, если тебе очень нужно, то файлы можно читать в любом месте с помощью класса RandomAccessFile.

Класс ResultSet тоже позволяет что-то подобное и позволяет двигать текущую строку по результату куда угодно. Для этого у него есть такие методы:

Метод Описание
1 next() Переключиться на следующую строку
2 previous() Переключиться на предыдущую строку
3 isFirst() Текущая строка первая?
4 isBeforeFirst() Мы перед первой строкой?
5 isLast() Текущая строка последняя?
6 isAfterLast() Мы после последней строки?
7 absolute(int n) Делает N-ю строку текущей
8 relative(int n) Двигает текущую строку на N позиций вперед. N может быть <0
9 getRow() Возвращает номер строки

Методы достаточно простые, однако нужно сделать два пояснения. Результаты как бы обрамлены пустыми строками с обоих сторон. Поэтому изначально текущая строка находится перед первой строкой результата. И чтобы получить первую строку, нужно хотя бы раз вызвать метод next().

Если ты на последней стоке вызвал метод next(), то ты перешел на строку после последней. Данных из нее прочитать ты не можешь, но никакой ошибки не произойдет. Тут метод isAfterLast() будет возвещать true в качестве результата.

Пример:

Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery("SELECT * FROM user");

System.out.println( results.getRow() );        	// 0
System.out.println( results.isBeforeFirst() );  // true
System.out.println( results.isFirst() );          	// false

results.next();

System.out.println( results.getRow() );        	// 1
System.out.println( results.isBeforeFirst() );  // false
System.out.println( results.isFirst() );          	// true

results.next();

System.out.println( results.getRow() );        	// 2
System.out.println( results.isBeforeFirst() );  // false
System.out.println( results.isFirst() );          	// false

Получение данных из текущей строки

Ты научился виртуозно управлять текущей строкой. Теперь давай разберем, как из нее получать данные. Для этого у объекта ResultSet есть специальные методы, которые все можно описать одним шаблоном:

getType(номерКолонки)

Впрочем, если у колонки есть имя, то можно получать и по имени колонки:

getType(имяКолонки)

Пример:

while (results.next()) {
        	Integer id = results.getInt(“id”);
        	String name = results.getString(“name”);
        	System.out.println(results.getRow() + ". " + id + "\t"+ name);
}

Ниже я приведу таблицу, которая тебе поможет связать типы данных SQL и методы ResultSet:

SQL Datatype getXXX() Methods
CHAR getString()
VARCHAR getString()
INT getInt()
FLOAT getDouble()
CLOB getClob()
BLOB getBlob()
DATE getDate()
TIME getTime()
TIMESTAMP getTimestamp()

Суть, думаю, ты понял.

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

Как читать данные из текущей строки мы разобрались: и по номеру колонки, и по ее имени. Кстати, а как узнать имя колонки по ее номеру? Или количество колонок в результате?

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

Для этого у JDBC есть специальный объект – интерфейс ResultSetMetaData. Получить объект этого типа достаточно просто:

Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery("SELECT * FROM user");
ResultSetMetaData resultSetMetaData = results.getMetaData();

У интерфейса ResultSetMetaData есть очень интересные методы. Ниже приведу самые популярные из них:

1 getColumnCount() Возвращает количество колонок результата
2 getColumnName(int column) Возвращает имя колонки
3 getColumnLabel(int column) Возвращает description колонки
4 getColumnType() Возвращает тип колонки: число (специальный код)
5 getColumnTypeName() Возвращает тип колонки: строка
6 getColumnClassName() Возвращает имя java-класса для типа колонки
7 getTableName() Возвращает имя таблицы
8 getCatalogName() Возвращает имя каталога колонки
9 getSchemaName() Возвращает имя схемы базы данных
10 isAutoIncrement(int column) Колонка поддерживает AUTO INCREMENT?
11 isNullable() Колонка может содержать NULL?

Давай с его помощью немного узнаем о нашей таблице:

ResultSetMetaData metaData = results.getMetaData();
int columnCount = metaData.getColumnCount();
for (int column = 1; column <= columnCount; column++)
{
        	String name = metaData.getColumnName(column);
        	String className = metaData.getColumnClassName(column);
        	String typeName = metaData.getColumnTypeName(column);
        	int type = metaData.getColumnType(column);

        	System.out.println(name + "\t" + className + "\t" + typeName + "\t" + type);
}

Важно! Обрати внимание, что колонки нумеруются с 1. Строки, кстати, тоже. Как это необычно, да?

И вот какой результат я получил после запуска программы:

"C:\Program Files\Java\jdk-17.0.3.1\bin\java.exe…
id java.lang.Integer INT 4
name java.lang.String VARCHAR 12
level java.lang.Integer INT 4
created_date java.sql.Date DATE 91
Process finished with exit code 0
1
Задача
Модуль 4. Работа с БД,  7 уровень2 лекция
Недоступна
task0704
В методе main создай подключение к БД с помощью метода getConnection(String, String, String) класса DriverManager. Используй URL "jdbc:mysql://localhost:3306/test", пользователя "root" и такой же пароль. Получи Statement используя метод createStatement без параметров. С помощью
1
Задача
Модуль 4. Работа с БД,  7 уровень2 лекция
Недоступна
task0705
В методе main создай подключение к БД с помощью метода getConnection(String, String, String) класса DriverManager. Используй URL "jdbc:mysql://localhost:3306/test", пользователя "root" и такой же пароль. Получи Statement используя метод createStatement без параметров. Выведи в к
1
Задача
Модуль 4. Работа с БД,  7 уровень2 лекция
Недоступна
task0706
В методе main создай подключение к БД с помощью метода getConnection(String, String, String) класса DriverManager. Используй URL "jdbc:mysql://localhost:3306/test", пользователя "root" и такой же пароль. Получи Statement используя метод createStatement без параметров. Выполни за
Комментарии (9)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Андрей
Уровень 109
28 ноября 2024, 09:09
Вопрос давно висит, может кто в курсе... При запуске задач в браузере выходит сообщение: - "Эта задача не может быть запущена на сервере JavaRush. Используйте свою любимую IDE." В требованиях условия задачи: -"В консоль должны быть выведены названия и типы всех колонок согласно условию." В своей любимой IDE, также выводит Exception. Я так понимаю из-за отсутствия подключения не существующих баз данных на моем локал хосте. У кого нибудь получилось запустить задачи этой лекции? Или я один тут решаю на уровне логического мышления, с выводом результата в голове...
Роман
Уровень 88
5 января 2025, 12:32
ну, не один во всяком случае
Артём
Уровень 112
30 июня 2025, 15:12
К сожалению, джавараш не снабдил нас тут готовой базой для решения задач, хотя, это можно было бы сделать, решая задачи из предыдущих уровеней. Чтобы задачи запускались, нужно - иметь на компьютере запущенную MySQL, - в проект джавараш добавить JDBC драйвер для MySQL, например, MySQL Connector/J, - создать базу task и в ней таблицу employee, которую можно взять из предыдущих модулей и чуть-чуть подпилить под текущие задачи.
Алексей
Уровень 115
19 августа 2025, 14:24
Лично у меня все БД со всеми таблицами из задач в голове. Я не запускаю никакой сервер, а просто решаю и отправляю на проверку. Что и вам рекомендую 🤪
Иван
Уровень 92
Expert
30 сентября 2023, 16:41
Разве ResultSet это класс ?
29 октября 2022, 15:59
задача 0706. Я конечно не специалист, но надо или условие проверить, или правильное решение. Пример вывода: id(INT) name(VARCHAR) age(INT) smth(VARCHAR) - те надо в строчку через пробел вывести. А решение задачи зачтется, только когда они будут выводиться в столбик.
Pixta
Уровень 108
Expert
2 ноября 2022, 07:28
у меня через print в строчку тоже приняло
5 ноября 2022, 15:33
ну слушай странно, у меня почему-то не зашло)
Stas S
Уровень 108
Expert
16 ноября 2022, 07:12
Проходит и с println и с обычным print, если после скобки делать отступ.