ЗАНЯТИЕ №3
Изучение интерфейсов ResultSet, ResultSetMetaData и DatabaseMetaData.
Интерфейс ResultSet определяет методы, которые позволяют работать с данными, полученными в результате выполнения запроса в базу данных. Результаты запроса помещаются в объект типа ResultSet и являются логическим представлением строк и столбцов данных, хранящихся в базе.
Существует три варианта объектов типа ResultSet: Standard, Scrollable и Updateable. При использовании стандартного варианта обновление полученного результата запроса невозможно, а перемещение по строкам результата запроса возможно только в одном направлении: от первой к последней записи. Вариант Scrollable позволяет перемещаться по строкам запроса как в прямом, так и в обратном направлении, а также позиционировать курсор как на абсолютную, так и на относительную текущей позицию. Вариант Updateable позволяет изменять данные результата запроса, вставлять и удалять строки. Оба последних варианта будут выполняться более медленно, чем стандартный вариант использования объекта типа ResultSet. По этому их лучше использовать только в необходимых для этого случаях.
При работе со стандартным вариантом использования объектов типа ResultSet используются следующие методы:
next() - перемещает курсор на следующую строку результата запроса;
isBeforeFirst() - Возвращает true если курсор находится на позиции “до первой записи” (BFR);
isFirst() - Возвращает true если курсор указывает на первую запись;
isAfterLast() - Возвращает true если курсор находится на позиции “после последней записи” (ALR);
isLast() - Возвращает true если курсор указывает на последнюю запись;
getRow() - Возвращает integer значение номера строки в результате запроса. 1 – первая строка; 2 – вторая строка и т.д. Метод возвращает 0 если строк не существует либо курсор находится в позиции BFR либо ALR.
Для изучения методов стандартного варианта использования объектов типа ResultSet необходимо создать класс с методом main, который регистрирует драйвер JDBC, устанавливает соединение, подготавливает и выполняет запрос в базу данных и демонстрирует использование перечисленных выше методов аналогично следующему примеру:
//Пример №3-1 // ResultSet rs = ...; System.out.println("Row number "+rs.getRow()+"; BFR is "+rs.isBeforeFirst()); while (rs.next()) { System.out.print("Row number "+rs.getRow()+"; First is "+rs.isFirst()); System.out.print(":\t"+rs.getInt(1)); System.out.println("\t"+rs.getString(2)); System.out.println("Row number "+rs.getRow()+"; Last is "+rs.isLast()); } System.out.println("Row number "+rs.getRow()+"; ALR is "+rs.isAfterLast());
Два других варианта использования объектов типа ResultSet требуют указания дополнительных параметров методам createStatement(), prepareStatement() и prepareCall():
createStatement(int resultSetType, int resultSetConcurrency);
prepareStatement(String sql, int resultSetType, int resultSetConcurrency);
prepareCall(String sql, int resultSetType, int resultSetConcurrency).
Первый параметр resultSetType используется для создания Scrollable ResultSet. Он задает возможность перемещения курсора в разных направления по строкам результата запроса и определяет чувствительность к изменениям данных, которые были изменены в базе после выполнения запроса. Параметр resultSetType может принимать следующие интуитивно понятные значения:
TYPE_SCROLL_INSENSITIVE – предусматривает перемещение курсора в любых направлениях, допускает абсолютное и относительное позиционирование курсора. Не отражает изменений данных, сделанных в базе после выполнения запроса.
TYPE_SCROLL_SENSITIVE - предусматривает перемещение курсора в любых направлениях, допускает абсолютное и относительное позиционирование курсора. Отражает изменения данных, сделанных в базе после выполнения запроса.
TYPE_FORWARD_ONLY – параметр по умолчанию, стандартный ResultSet.
Второй параметр resultSetConcurrency отвечает за возможность изменения данных результата запроса, вставки и удаления строк из базы данных. Он может принимать одно из двух значений:
CONCUR_UPDATABLE – позволяет вносить изменения в данные;
CONCUR_READ_ONLY – параметр по умолчанию, стандартный ResultSet.
При работе со Scrollable и Updateable вариантами объектов типа ResultSet используются следующие методы:
next() - перемещает курсор на следующую строку результата запроса;
previous() - перемещает курсор на предыдущую строку результата запроса;
beforeFirst() - устанавливает курсор на позицию “до первой строки”; если сразу после выполнения этого метода выполнить метод getXXX() будет выдано исключение типа SQLException;
afterLast() - устанавливает курсор на позицию “после последней строки”; если сразу после выполнения этого метода выполнить метод getXXX() будет выдано исключение типа SQLException;
first() - устанавливает курсор на первую строку результата запроса;
last() - устанавливает курсор на последнюю строку результата запроса;
absolute() - устанавливает курсор на указанную строку относительно первой строки результата запроса;
relative() - устанавливает курсор на указанную строку относительно текущей строки;
moveToCurrentRow() - устанавливает курсор на строку, номер которой был запомнен в результате выполнения метода moveToInsertRow();
moveToInsertRow() - устанавливает курсор в специальную свободную позицию для заполнения пустой строки значениями с помощью методов updateXXX() и последующей вставки этой строки в базу данных с помощью метода insertRow();
deleteRow() - удаляет строку как из результата запроса, так и из базы данных.
Для изучения перечисленных выше методов необходимо создать класс с методом main, который регистрирует драйвер JDBC, устанавливает соединение, подготавливает и выполняет запрос в базу данных и демонстрирует использование перечисленных выше методов аналогично следующим примерам:
//Пример №3-2 // ResultSet rs = ...; rs.afterLast(); System.out.println("Row number "+rs.getRow()+"; BFR is "+rs.isBeforeFirst()); rs.last(); while (rs.previous()) { System.out.print("Row number "+rs.getRow()+"; First is "+rs.isFirst()); System.out.print(":\t"+rs.getInt(1)); System.out.println("\t"+rs.getString(2)); System.out.println("Row number "+rs.getRow()+"; Last is "+rs.isLast()); } System.out.println("Row number "+rs.getRow()+"; ALR is "+rs.isAfterLast()); //Пример №3-3 // Statement st = conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = st.executeQuery("SELECT * FROM операторы_связи"); while (rs.next()) { System.out.println(rs.getInt(1)+"\t"+rs.getString(2)); if(rs.getString(2).equals("МТС")) { rs.updateString(2, "TELE2"); rs.updateRow(); } } //rs = st.executeQuery("SELECT * FROM операторы_связи"); rs.beforeFirst(); while (rs.next()) { System.out.println(rs.getInt(1)+"\t"+rs.getString(2)); } //Пример 3-4 // Statement st = ...; ResultSet rs = ...; while (rs.next()) { System.out.println(rs.getInt(1)+"\t"+rs.getString(2)); if(rs.getString(2).equals("SkyLink2")) { rs.deleteRow(); } } rs.moveToInsertRow(); rs.updateInt(1, 5); rs.updateString(2, "TELE2"); rs.insertRow(); //rs = st.executeQuery("SELECT * FROM операторы_связи"); rs.beforeFirst(); while (rs.next()) { System.out.println(rs.getInt(1)+"\t"+rs.getString(2)); }
Интерфейсы ResultSetMetaData и DatabaseMetaData предусматривают методы для работы с метаданными базы данных. Первый интерфейс предназначен для получения информации о данных результата запроса, таких как имена столбцов, типы данных, максимальная длина. Второй интерфейс необходим для получения данных о структуре базы данных, таких как имена таблиц, первичные и внешние ключи, типы данных. Объекты такого типа используются для написания универсальных методов обработки результатов запросов либо для создания системных приложений администрирования баз данных.
Объект типа ResultSetMetaData создается методом getMetaData() объекта типа ResultSet. Ниже перечислены некоторые наиболее часто используемые методы объекта типа ResultSetMetaData:
getTableName() - Возвращает имя таблицы, по которой выполнялся запрос; тип возвращаемого значения String.
getColumnCount() - Возвращает количество столбцов результата запроса; тип возвращаемого значения int.
getColumnName(int n) – Возвращает имя столбца номер n в результате запроса; тип возвращаемого значения String.
getColumnType(int n) – Возвращает JDBC тип данных столбца номер n результата запроса (java.sql.Types); тип возвращаемого значения int.
GetColumnTypeName(int n) – Возвращает имя типа данных столбца номер n результата запроса в соответствии с типом данных его в базе данных (SQL data types); тип возвращаемого значения String.
Номер столбца результата запроса, так же как и в базе данных нумеруется начиная с 1, а не с 0, как при работе с массивами. Попытка указать нулевой номер столбца приведет к появлению исключения типа SQLException.
Объект типа DatabaseMetaData создается методом getMetaData() объекта типа Connection. Метода полученного таким образом объекта можно разделить условно на две категории: характеристики и струкрура базы данных.
К первой категории относятся методы для получения такой информации, как список ключевых слов SQL, перечень SQL типов данных, поддерживаемых данной СУБД. Типами возвращаемого значения таких методов могут быть одиночные строки или строки, разделенные символом “точка”. Методы, предназначенные для получения количественных характеристик базы данных возвращают значение типа int, например: максимально допустимое количество активных соединений. Методы, предназначенные для получения информации типа поддерживается ли базой данных пакетное обновление, возвращают значение типа boolean.
Ко второй категории относятся методы, запрашивающие информацию о таблицах, хранимых процедурах и т.д. Такие методы возвращают объекты типа ResultSet. Параметры таких методов могут содержать метасимволы _ (любой одиночный символ) и % (любая последовательность символов).
Изучение интерфейсов ResultSetMetaData и DatabaseMetaData выносится на самостоятельную проработку. Для проверки изученного материала будет выдано индивидуальное контрольное задание, заключающееся в написании соответствующего программного кода на java, которое необходимо выполнить и защитить на контрольном занятии.