В прошлом уроке мы рассмотрели понятие Statements и их виды. Мы узнали, что в результате SQL – запроса мы получаем данные.
Данные, полученные в результате SQL – запроса возвращаются в виде множества результатов, которые хранятся в сущности под названием Result Set.
Стандартный способ получить записи из нашей базе данных (далее – БД) – это применение ключевого слова SELECT. Стандартный способ просмотреть эти данные – это использовать Result set.
Интерфейс java.sql.ResultSet представляет собой множество результатов, запроса в БД.
Экземпляр ResultSet имеет указатель, который указывает на текущую строку в полученном множестве.
Все методы интерфейса java.sql.ResultSet мы можем разделить на три большие группы:
- Методы получения данных.
Эти методы используются для просмотра данных конкретной записи, на которую ссылается указатель. - Методы изменения данных.
Методы этой группы используются для изменения данных текущей записи. Эти изменения передаются в используемую БД. - Методы навигации.
Эти методы используются для перемещения указателя.
Курсор двигается на основе свойств ResultSet. Эти свойства указываются при создании экземпляра ResultSet.
Для определения этих свойств используются следующие методы:
- createStatement (int RSType, int RSConcurrency);
- prepareStatement (String SQL, int RSType, int RSConcurrency);
- prepareCall (String SQL, int RSType, int RSConcurrency);
Аргумент RSType определяет тип ResultSet, а второй – определяет, используется ли данный экземпляр ResultSet только для чтения, или для чтения и изменения также.
Типы ResultSet
Возможные типы ResultSet приведены ниже. Тип TYPE_FORWARD_ONLY используется по умолчанию.
Рассмотрим эти типы:
- ResultSet.TYPE-FORWARD_ONLY
Указатель двигается только вперёд по множеству полученных результатов.
. - ResultSet.TYPE_SCROLL_INSENSITIVE
Указатель может двигаться вперёд и назад и не чувствителен к изменениям в БД, которые сделаны другими пользователями после того, как ResultSet был создан. - ResultSet.TYPE_SCROLL_SENSITIVE
Указатель может двигаться вперёд и назад и чувствителен к изменениям в БД, которые сделаны другими пользователями после того, как ResultSet был создан.
Доступ ResultSet
По умолчанию RSConcurrency экземпляра ResultSet установлен тип CONCUR_READ_ONLY, т.е. только для чтения.
Всего существует два типа этого параметра:
- ResultSet.CONCUR_READ_ONLY
Создаёт экземпляр ResultSet только для чтения. Устанавливается по умолчанию. - ResultSet.CONCUR_UPDATABLE
Создаёт экземпляр ResultSet, который может изменять данные.
В виде кода, создание экземпляра ResultSet с необходимыми нам параметрами выглядит, примерно так:
try {
statement = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
} catch (SQLException e) {
e.printStackTrace();
} finally {
/*do some job*/
}
Навигация по ResultSet
В интерфейсе java.sql.ResultSet существует несколько методов для перемещения указателя.
Некоторые из них приведены ниже:
- public void beforeFirst () throws SQLException
Перемещает указатель на место перед первым рядом. - public void afterLast () throws SQLException
Перемещает указатель на место после крайнего ряда. - public boolean first () throws SQLException
Перемещает указатель на первый ряд. - public boolean last () throws SQLException
Перемещает указатель на крайний ряд. - public boolean previous () throws SQLException
Перемещает указатель на предыдущий ряд. Возвращает false, если предыдущий ряд находится за пределами множества результатов. - public boolean next () throws SQLException
Перемещает указатель на следующий ряд. Возвращает false, если следующий ряд находится за пределами множества результатов. - public void absolute (int row) throws SQLException
Перемещает указатель на указанный ряд. - public void relative (int row) throws SQLException
Перемещает указатель на указанное количество рядов от текущего - public int getRow () throws SQLException
Возвращает номер ряда, на который в данный момент указывает курсор. - public void moveToInsertRow () throws SQLException
Перемещает указатель на ряд в полученном множестве, который может быть использован для того, чтобы добавить новую запись в БД. Текущее положение указателя запоминается. - public void moveToCurrentRow () throws SQLExcpetion
Возвращает указатель обратно на текущий ряд в случае, если указатель ссылается на ряд, в который в данный момент добавляются данные.
Для понимания того, как это работает на практике, рассмотрим пример простого приложения.
import java.sql.*;
public class ResultSetNavigationDemo {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DATABASE_URL = "jdbc:mysql://localhost/PROSELYTE_TUTORIALS";
static final String USER = "ВАШЕ_ИМЯ_ПОЛЬЗОВАТЕЛЯ";
static final String PASSWORD = "ВАШ_ПАРОЛЬ";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Connection connection = null;
Statement statement = null;
Class.forName(JDBC_DRIVER);
connection = DriverManager.getConnection(DATABASE_URL, USER, PASSWORD);
System.out.println("Creating statement...");
try {
statement = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE
);
String SQL = "SELECT * FROM developers";
ResultSet resultSet = statement.executeQuery(SQL);
System.out.println("Moving cursor to the last position...");
resultSet.last();
System.out.println("Getting record...");
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String specialty = resultSet.getString("specialty");
int salary = resultSet.getInt("salary");
System.out.println("Last record in result set:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Moving cursor to previous row...");
resultSet.previous();
System.out.println("Getting record...");
id = resultSet.getInt("id");
name = resultSet.getString("name");
specialty = resultSet.getString("specialty");
salary = resultSet.getInt("salary");
System.out.println("Previous record:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Moving cursor to the first row...");
resultSet.first();
System.out.println("Getting record...");
id = resultSet.getInt("id");
name = resultSet.getString("name");
specialty = resultSet.getString("specialty");
salary = resultSet.getInt("salary");
System.out.println("First record:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Adding record...");
SQL = "INSERT INTO developers VALUES (5, 'Mike', 'PHP', 1500)";
statement.executeUpdate(SQL);
SQL = "SELECT * FROM developers";
resultSet = statement.executeQuery(SQL);
resultSet.last();
System.out.println("Getting record...");
id = resultSet.getInt("id");
name = resultSet.getString("name");
specialty = resultSet.getString("specialty");
salary = resultSet.getInt("salary");
System.out.println("Last record:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Full list of records:");
SQL = "SELECT * FROM developers";
resultSet = statement.executeQuery(SQL);
while (resultSet.next()) {
id = resultSet.getInt("id");
name = resultSet.getString("name");
specialty = resultSet.getString("specialty");
salary = resultSet.getInt("salary");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement != null) {
statement.close();
}
if(connection!=null){
connection.close();
}
}
}
}
В результате работы программы мы получим, следующий результат:
/*Some System Messages*/
Creating statement...
Moving cursor to the last position...
Getting record...
Last record in result set:
id: 4
Name: Eugene
Specialty: Java
Salary: $3000
=========================
Moving cursor to previous row...
Getting record...
Previous record:
id: 3
Name: AsyaSmile
Specialty: UI/UX
Salary: $2000
=========================
Moving cursor to the first row...
Getting record...
First record:
id: 1
Name: Proselyte
Specialty: Java
Salary: $3000
=========================
Adding record...
Getting record...
Last record:
id: 5
Name: Mike
Specialty: PHP
Salary: $1500
=========================
Full list of records:
id: 1
Name: Proselyte
Specialty: Java
Salary: $3000
=========================
id: 2
Name: Peter
Specialty: C++
Salary: $3000
=========================
id: 3
Name: AsyaSmile
Specialty: UI/UX
Salary: $2000
=========================
id: 4
Name: Eugene
Specialty: Java
Salary: $3000
=========================
id: 5
Name: Mike
Specialty: PHP
Salary: $1500
=========================
Просмотр результатов ResultSet
Для получения и редактирования данных, в интерфейса ResultSet существует множество методов.
Мы можем получить данные, как по имени, так и индексу:
- public int getInt (int columnIndex) throws SQLException
Возвращает номер текущего ряда с указанным индексом колонки. Индексы начинаются с 1. Т.е. первая – 1, вторая – 2 и т.д. - public int getInt (String columnName) throws SQLException
Возвращает целое число в текущем ряду с колонкой с именем, переданном в параметре columnName.
Существуют также методы для получения определённых типов данных SQL (java.sql.Time, java.sql.Date и т.д.).
Для понимания того, как это работает на практике, рассмотрим следующий пример.
Пример:
import java.sql.*;
public class ResultSetViewDemo {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DATABASE_URL = "jdbc:mysql://localhost/PROSELYTE_TUTORIALS";
static final String USER = "ВАШЕ_ИМЯ_ПОЛЬЗОВАТЕЛЯ";
static final String PASSWORD = "ВАШ_ПАРОЛЬ";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Connection connection = null;
Statement statement = null;
Class.forName(JDBC_DRIVER);
connection = DriverManager.getConnection(DATABASE_URL, USER, PASSWORD);
System.out.println("Creating statement...");
try {
statement = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE
);
String SQL = "SELECT * FROM developers";
ResultSet resultSet = statement.executeQuery(SQL);
System.out.println("Moving cursor to the last position...");
resultSet.last();
System.out.println("Getting record (by name)...");
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String specialty = resultSet.getString("specialty");
int salary = resultSet.getInt("salary");
System.out.println("Last record in result set:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Moving cursor to previous row...");
resultSet.previous();
System.out.println("Getting record...");
id = resultSet.getInt("id");
name = resultSet.getString("name");
specialty = resultSet.getString("specialty");
salary = resultSet.getInt("salary");
System.out.println("Previous record:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Moving cursor to the first row...");
resultSet.first();
System.out.println("Getting record...");
id = resultSet.getInt("id");
name = resultSet.getString("name");
specialty = resultSet.getString("specialty");
salary = resultSet.getInt("salary");
System.out.println("First record:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Adding record...");
SQL = "INSERT INTO developers VALUES (5, 'Mike', 'PHP', 1500)";
statement.executeUpdate(SQL);
SQL = "SELECT * FROM developers";
resultSet = statement.executeQuery(SQL);
resultSet.last();
System.out.println("Getting record (by index)...");
id = resultSet.getInt(1);
name = resultSet.getString(2);
specialty = resultSet.getString(3);
salary = resultSet.getInt(4);
System.out.println("Last record:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
System.out.println("Full list of records (by name):");
SQL = "SELECT * FROM developers";
resultSet = statement.executeQuery(SQL);
while (resultSet.next()) {
id = resultSet.getInt("id");
name = resultSet.getString("name");
specialty = resultSet.getString("specialty");
salary = resultSet.getInt("salary");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
}
}
}
В результате работы программы мы получим следующий результат:
/*Some System Messages*/
Creating statement...
Moving cursor to the last position...
Getting record (by name)...
Last record in result set:
id: 4
Name: Eugene
Specialty: Java
Salary: $3000
=========================
Moving cursor to previous row...
Getting record...
Previous record:
id: 3
Name: AsyaSmile
Specialty: UI/UX
Salary: $2000
=========================
Moving cursor to the first row...
Getting record...
First record:
id: 1
Name: Proselyte
Specialty: Java
Salary: $3000
=========================
Adding record...
Getting record (by index)...
Last record:
id: 5
Name: Mike
Specialty: PHP
Salary: $1500
=========================
Full list of records (by name):
id: 1
Name: Proselyte
Specialty: Java
Salary: $3000
=========================
id: 2
Name: Peter
Specialty: C++
Salary: $3000
=========================
id: 3
Name: AsyaSmile
Specialty: UI/UX
Salary: $2000
=========================
id: 4
Name: Eugene
Specialty: Java
Salary: $3000
=========================
id: 5
Name: Mike
Specialty: PHP
Salary: $1500
=========================
Редактирование данных ResultSet
Для редактирования данных, в интерфейсе java.sql.ResultSet, также разработано множество методов.
Мы можем изменять данные, как по имени, так и по индексу колонки:
- public void updateString (int columnIndex, String s) throws SQLException
Изменяет строку в указанной колонке. - public void updateString (String columnName, String s) throws SQLException
Изменяет строку в колонке с указанным именем.
Мы также можем работать с рядами в таблице БД:
- public void insertRow()
Вставляет запись в таблицу БД. Может быть использован только в том случае, когда указатель ссылается на ряд для вставки. - public void updateRow()
Изменяет текущий ряд в таблице БД. - public void deleteRow()
Удаляет текущий ряд из таблицы БД.
Для понимания того, как это работает на практике, рассмотрим такой пример.
Пример:
import java.sql.*;
public class ResultSetUpdateDemo {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DATABASE_URL = "jdbc:mysql://localhost/PROSELYTE_TUTORIALS";
static final String USER = "ВАШЕ_ИМЯ_ПОЛЬЗОВАТЕЛЯ";
static final String PASSWORD = "ВАШ_ПАРОЛЬ";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Connection connection = null;
Statement statement = null;
Class.forName(JDBC_DRIVER);
connection = DriverManager.getConnection(DATABASE_URL, USER, PASSWORD);
System.out.println("Creating statement...");
try {
statement = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE
);
String SQL = "SELECT * FROM developers";
ResultSet resultSet = statement.executeQuery(SQL);
System.out.println("Initial list of records:");
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String specialty = resultSet.getString("specialty");
int salary = resultSet.getInt("salary");
System.out.println("Last record in result set:");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
}
System.out.println("Increasing all developer's salary (+ $1,000)...");
resultSet.first();
while (resultSet.next()) {
int newSalary = resultSet.getInt("salary") + 1000;
resultSet.updateInt("salary", newSalary);
resultSet.updateRow();
}
resultSet.first();
System.out.println("Final list of records:");
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String specialty = resultSet.getString("specialty");
int salary = resultSet.getInt("salary");
System.out.println("id: " + id);
System.out.println("Name: " + name);
System.out.println("Specialty: " + specialty);
System.out.println("Salary: $" + salary);
System.out.println("\n=========================\n");
}
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
}
}
}
В результате работы программы мы получим следующий результат:
Creating statement...
Initial list of records:
Last record in result set:
id: 1
Name: Proselyte
Specialty: Java
Salary: $3000
=========================
Last record in result set:
id: 2
Name: Peter
Specialty: C++
Salary: $3000
=========================
Last record in result set:
id: 3
Name: AsyaSmile
Specialty: UI/UX
Salary: $2000
=========================
Last record in result set:
id: 4
Name: Eugene
Specialty: Java
Salary: $3000
=========================
Last record in result set:
id: 5
Name: Mike
Specialty: PHP
Salary: $1500
=========================
Increasing all developer's salary (+ $1,000)...
Final list of records:
id: 2
Name: Peter
Specialty: C++
Salary: $4000
=========================
id: 3
Name: AsyaSmile
Specialty: UI/UX
Salary: $3000
=========================
id: 4
Name: Eugene
Specialty: Java
Salary: $4000
=========================
id: 5
Name: Mike
Specialty: PHP
Salary: $2500
=========================
В этом уроке мы изучили такой важный элемент, как ResultSet, его методы, применение и рассмотрели примеры приложений с его использованием.
В следующем уроке мы изучим типы данных JDBC.