Result Set
Данные, полученные в результате 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_INTENSIVE
Указатель может двигаться вперед и назад и не чувствителен к изменениям в БД, которые сделаны другими пользователями после того, как 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
=========================