Что такое resultset как с ним работать
Перейти к содержимому

Что такое resultset как с ним работать

  • автор:

Что такое resultset как с ним работать

Изучение интерфейсов 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, которое необходимо выполнить и защитить на контрольном занятии.

Продвинутая работа с ResultSet

Современный JDBC API позволяет очень сильно кастомизировать объекты Statement и ResultSet . Например, с помощью ResultSet можно менять строки в базе данных.

При создании объекта statement в него можно передать кучу наших пожеланий. Эти пожелания можно разделить на три группы:

  • Тип связи с базой
  • Управление одновременным доступом
  • Сохраняемость и транзакции

Эти параметры можно передавать при создании объекта Statement или PreparedStatement . Пример:

 Statement statement = connection.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_OVER_COMMIT ); PreparedStatement statement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_OVER_COMMIT); 

Глубоко эти вещи мы изучать не будем, но я хочу, чтобы ты знал, что такое возможно, если встретишь что-то похожее в чужом коде.

Типы ResultSet

ResultSet может быть определенного типа. Тип определяет некоторые характеристики и возможности ResultSet.

Не все типы поддерживаются всеми базами данных и драйверами JDBC. Тебе придется проверить свою базу данных и драйвер JDBC, чтобы увидеть, поддерживает ли он тип, который ты хочешь использовать. Метод DatabaseMetaData.supportsResultSetType(int type) возвращает true или false в зависимости от того, поддерживается данный тип или нет.

На момент написания статьи существует три типа ResultSet:

  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE

Тип по умолчанию — TYPE_FORWARD_ONLY.

TYPE_FORWARD_ONLY означает, что ResultSet можно перемещать только вперед. То есть ты можешь перемещаться только из строки 1, строки 2, строки 3 и т. д. В ResultSet ты не можешь двигаться назад: нельзя считать данные из 9-й строки после чтения десятой.

TYPE_SCROLL_INSENSITIVE означает, что ResultSet можно перемещать (прокручивать) как вперед, так и назад. Ты также можешь перейти к позиции относительно текущей позиции или перейти к абсолютной позиции.

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

TYPE_SCROLL_SENSITIVE означает, что ResultSet можно перемещать (прокручивать) как вперед, так и назад. Ты также можешь перейти к позиции относительно текущей позиции или перейти к абсолютной позиции.

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

Concurrency

Параллельность ResultSet определяет, может ли ResultSet обновляться, или только считываться.

Некоторые базы данных и драйверы JDBC поддерживают обновление ResultSet, но не все. Метод DatabaseMetaData.supportsResultSetConcurrency(int concurrency) возвращает значение true или false в зависимости от того, поддерживается данный режим параллелизма или нет.

ResultSet может иметь один из двух уровней параллелизма:

CONCUR_READ_ONLY означает, что ResultSet может быть только прочитан.

CONCUR_UPDATABLE означает, что ResultSet может быть прочитан и изменен.

Пример изменения данных в базе

С помощью этих параметров ты можешь управлять создаваемым Statement и его ResultSet.

Например, можно создать обновляемый ResultSet и с его помощью менять базу данных. При создании Statement важно соблюсти следующие условия:

  • указывается только одна таблица
  • не содержит предложений join или group by
  • столбцы запроса должны содержать первичный ключ

При выполнении вышеуказанных условий обновляемый ResultSet может быть использован для модификации таблицы в базе данных. При создании объекта Statement нужно указать такие параметры:

 Statement st = createStatement(Result.TYPE_SCROLL_INSENSITIVE, Result.CONCUR_UPDATABLE) 

Результатом выполнения такого оператора является обновляемый набор результатов. Метод обновления заключается в перемещении курсора ResultSet в строку, которую ты хочешь обновить, а затем в вызове метода updateXXX() .

Метод updateXXX работает аналогично методу getXXX() . Метод updateXXX() имеет два параметра. Первый — это номер обновляемого столбца, который может быть именем столбца или серийным номером. Второй — это данные, которые необходимо обновить, и этот тип данных должен быть тот же, что и XXX.

Чтобы строка реально обновилась в базе, нужно вызвать метод updateRow() до того, как курсор ResultSet покинет измененную строку, в противном случае изменения так и не попадут в базу.

Также можно добавлять новые строки в таблицу:

Сначала нужно переместить курсор на пустую строку. Для этого нужно вызвать метод moveToInsertRow() .

Затем нужно заполнить эту строку данными с помощью метода updateXXX() .

Затем нужно вызвать метод inserRow() , чтобы строка добавилась в базу.

Ну и наконец нужно вернуть курсор обратно, вызвав метод moveToCurrentRow() .

Важно! Не все СУБД поддерживают данные параметры для расширенного оператора Statement. В случае наличия проблем смотри официальную документацию конкретной СУБД.

Понимание работы ResultSet

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

Отслеживать
9,024 4 4 золотых знака 19 19 серебряных знаков 28 28 бронзовых знаков
задан 4 авг 2018 в 10:44
alex safsafsd alex safsafsd
796 1 1 золотой знак 6 6 серебряных знаков 17 17 бронзовых знаков

Это некий стек коллекции, собранный через подготовленный запрос, для возврата выборки и прохода по ней, если это потребуется.

4 авг 2018 в 10:57
@And То есть это все таки коллекция? тогда мы следовательно можем получить outofmemory?
4 авг 2018 в 11:00

Естественно, возвращает коллекцию строк выборки. Конечно можем получить OutOfMemory . Это будет отражать переполненный буфер памяти и вы, сами сможете в этом убедиться, если сделаете большую выборку, чем отведено для самого результата. За частую это бывает, когда данных больше, чем отведено памяти для запроса.

4 авг 2018 в 11:44
@And Ну я внизу уже ответил почему задал такой вопрос. Ответьте сообщением, я вам плюсик поставлю.
4 авг 2018 в 12:11
А какой смысл от ответа, если вы, уже выбрали для вас правильный ответ?
4 авг 2018 в 13:41

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

То есть по сути он не имеет данных, кроме как сведений о курсоре?

Нет, это не верно.

В определении ResultSet сказано:

Что это — таблица данных, представляющая набор результатов базы данных, который обычно генерируется путем выполнения утверждения, выполняющего запрос к базе данных.

getFetchSize() определяет сколько записей считывает запрос, и устаналивается в утверждении Statement :

int getFetchSize () throws SQLException

Получает количество строк набора результатов, которое является размером выборки по умолчанию для объектов ResultSet , сгенерированных из этого объекта Statement . Если этот объект Statement не установил размер выборки, вызвав метод setFetchSize , возвращаемое значение будет специфичным для реализации.

Что такое resultset как с ним работать

Изучение семейства интерфейсов RowSet:

JdbcRowSet, CachedRowSet, WebRowSet

Объекты типа RowSet являются альтернативой объектам типа ResultSet. Интерфейс RowSet расширяет интерфейс ResultSet и определяет дополнительные методы, которые позволяют работать с компонентной архитектурой JavaBean. Кроме того, объекты данного типа могут использоваться при отсутствии постоянного соединения с базой данных. При этом объект типа RowSet будет автоматически соединяться с базой при необходимости получения из нее данных. Интерфейс входит в пакет javax.sql и должен быть реализован поставщиком JDBC классов (драйверов).

Для использования реализации возможностей данного интерфейса компанией Oracle необходимо импортировать пакет oracle.jdbc.rowset, который находится в архиве ocrs12.jar. После чего можно использовать классы OracleCachedRowSet, OracleJDBCRowSet и OracleWebRowSet, применяющие интерфейс javax.sql.RowSet.

Интерфейсы ResultSet и RowSet имеют два принципиальных отличия:

1. Интерфейс RowSet поддерживает компонентную модель JavaBeans. Это позволяет изменять свойства объектов используя визуальные средства разработки компонентов. Кроме того, объекты типа RowSet могут информировать службы обработки событий, например о событии обновления строк.

2. Объекты типа RowSet могут использоваться как при наличии постоянного соединения с базой данных, так и при отсутствии соединения. В режиме постоянного соединения с базой данных использование объектов типа RowSet аналогично использованию объектов типа ResultSet. В режиме отсутствия постоянного соединения наличие соединения с базой данных необходимо только при заполнении объекта типа RowSet данными из базы. После чего соединение разрывается автоматически и данные для обработки будут выбираться далее из памяти.

Еще одно полезное преимущество интерфейса RowSet состоит в реализации прокручиваемых и обновляемых курсоров в виде надстройки над драйверами, которые сами этого не поддерживают.

Объекты типа RowSet могут создавать события, что позволяет оповещать о их происхождении другие компоненты JavaBeans, применяющие интерфейс RowSetListener, который предусматривает три основных метода для обработки одноименных событий: rowChanged(), rowSetChenged() и cursorMoved(). Первое событие (row changes) происходит при изменении при изменении строки, например, когда выполняется UPDATE SQL-предложение. Следующее событие (rowset changes) происходит, когда клиент изменяет весь набор строк. И последнее событие (cursor movements) происходит при перемещении курсора с одной строки на другую, например при выполнении методов next(), previous() или relative().

Интерфейс RowSet не только расширяет интерфейс ResultSet, но и предусматривает установку некоторый свойств, заменяющих использование интерфейсов Connection, Statement, PreparedStatement и CallableStatement. Выполнение простого запроса с использованием интерфейса RowSet может выглядеть следующим образом:

import java.sql.*; import javax.sql.*; import oracle.jdbc.rowset.*; public class JdbcRS public static void main(String[] args) try OracleJDBCRowSet ojrs = new OracleJDBCRowSet(); ojrs.setUrl(«jdbc:oracle:thin:@localhost:1521:orbis»); ojrs.setUsername(«stud»); ojrs.setPassword(«stud»); ojrs.setCommand(«SELECT count(*) FROM н_люди»); ojrs.execute(); while (ojrs.next()) System.out.println(«Total count of row is: » + ojrs.getInt(1)); > > catch (SQLException se) se.printStackTrace(); > System.out.println(«Goodbye!»); > >

Соединение с базой данных устанавливается в момент выполнения метода execute(). При выполнении SQL-предложения SELECT объект типа RowSet заполняет себя удовлетворяющими условию запроса данными. Результаты выполнения SQL-предложений INSERT, UPDATE, DELETE и любых DML-предложений игнорируются. В случае ошибки возникает исключение SQLException. Если используется параметризованный запрос, то перед выполнением метода execute() необходимо установить все параметры методами setXXX(), как при использовании объектов типа PreparedStatement, например:

OracleCachedRowSet ocrs = new OracleCachedRowSet(); // ocrs.setUrl(«jdbc:oracle:thin:@localhost:1521:orbis»); ocrs.setUsername(«stud»); ocrs.setPassword(«stud»); String sql = «SELECT * FROM н_люди WHERE ид = ?»; ocrs.setCommand(sql); ocrs.setInt(1,123456); ocrs.execute();

Для извлечения данных из объекта типа RowSet можно использовать RowSet.getXXX() методы, XXX-одноименные с типами данных Java тех переменных, в которые эти данные будут сохранены. Перемещение курсора по набору данных объекта типа RowSet выполняется методами, унаследованными от интерфейса ResultSet:

next() — перемещает курсор на следующую строку результата запроса;

previous() — перемещает курсор на предыдущую строку результата запроса;

beforeFirst() — устанавливает курсор на позицию “до первой строки”; если сразу после выполнения этого метода выполнить метод getXXX() будет выдано исключение типа SQLException;

afterLast() — устанавливает курсор на позицию “после последней строки”; если сразу после выполнения этого метода выполнить метод getXXX() будет выдано исключение типа SQLException;

first() — устанавливает курсор на первую строку результата запроса;

last() — устанавливает курсор на последнюю сторк результата запроса;

absolute() — устанавливает курсор на указанную строку относительно первой строки результата запроса;

relative() — устанавливает курсор на указанную строку относительно текущей строки;

moveToCurrentRow() — устанавливает курсор на строку, номер которой был запомнен в результате выполнения метода moveToInsertRow();

moveToInsertRow() — устанавливает курсор в специальную свободную позицию для заполнения пустой строки значениями с помощью методов updateXXX() и последующей вставки этой строки в базу данных с помощью метода insertRow();

deleteRow() — удаляет строку как из результата запроса, так и из базы данных.

Для задания параметра прокрутки (scrollability) используется метод setType(). Он задает возможность перемещения курсора в разных направления по строкам результата запроса и определяет чувствительность к изменениям данных, которые были изменены в базе после выполнения запроса. Параметр прокрутки может принимать следующие:

TYPE_SCROLL_INSENSITIVE – предусматривает перемещение курсора в любых направлениях, допускает абсолютное и относительное позиционирование курсора. Не отражает изменений данных, сделанных в базе после выполнения запроса.

TYPE_SCROLL_SENSITIVE — предусматривает перемещение курсора в любых направлениях, допускает абсолютное и относительное позиционирование курсора. Отражает изменения данных, сделанных в базе после выполнения запроса.

TYPE_FORWARD_ONLY – параметр по умолчанию, стандартный ResultSet.

Второй параметр устанавливается методом setConcurrency() и отвечает за возможность изменения данных результата запроса, вставки и удаления строк из базы данных. Он может принимать одно из двух значений:

CONCUR_UPDATABLE – позволяет вносить изменения в данные;

CONCUR_READ_ONLY – не позволяет вносить изменения в данные.

Третий параметр позволяет контролировать уровень транзакций. Он определяет возможность доступа к данным объекта типа RowSet в течении транзакции с использованием данных другого объекта типа RowSet. Этот параметр устанавливается методом setTransactionIsolation() и может принимать следующие значения:

TRANSACTION_NONE – указывает, что соединение не поддерживает уровень транзакций;

TRANSACTION_READ_UNCOMMITTED – позволяет объекту типа RowSet читать «грязные», т.е. не подтвержденные (uncommitted) данные из других транзакций;

TRANSACTION_READ_COMMITTED – позволяет объекту типа RowSet читать только подтвержденные (committed) данные из других транзакций;

TRANSACTION_REPEATABLE_READ – предотвращает чтение объектом типа RowSet не подтвержденных (uncommitted) данных или данных, изменившихся после начала выполнения транзакции;

TRANSACTION_SERIALIZABLE – не позволяет объекту типа RowSet читать любые данные из других транзакций.

После завершения обработки данных объекта типа RowSet необходимо закрыть объект методом RowSet.close().

Из перечисленного выше семейства самой простой является реализация интерфейса JdbcRowSet. Работа с объектами типа JdbcRowSet требует постоянного соединения с базой данных. Кроме того, они не могут быть преобразованы в последовательную форму (не serializable), что ограничивает возможности их использования в распределенных системах обработки данных.

Реализация интерфейса CachedRowSet позволяет использовать не постоянное соединение и предоставляет возможность преобразования объектов типа CachedRowSet в последовательную форму, т.е. позволяет сохранять объекты. При отключении соединения объекты типа CachedRowSet создают внутри себя виртуальную таблицу, что позволяет работать с ними, как с отдельными независимыми объектами. После заполнения объекта данными можно сохранить его и использовать совместно сразу несколькими клиентами. Это позволяет уменьшить количество постоянных соединений с базой и сократить частоту их создания. Кроме того объект могут получить мобильные клиенты и использовать его отключившись от сетевого соединения. Ниже приведен пример создания, сохранения и использования объекта типа CachedRowSet:

import java.io.*; import java.sql.SQLException; import oracle.jdbc.rowset.OracleCachedRowSet; public class CachedRS //Constant to hold file name used to store the CachedRowSet private final static String CRS_FILE_LOC =»cachedrs.crs»; public static void main(String[] args) throws Exception try //Create serialized CachedRowSet writeCachedRowSet(); //Create CachedRowSet from serialized object OracleCachedRowSet crs = readCachedRowSet(); //Display values while(crs.next()) System.out.print(«Фамилия: » + crs.getString(«фамилия»)); System.out.print(«, Имя: » + crs.getString(«имя»)); System.out.print(«, Отчество: » + crs.getString(«отчество»)); System.out.print(«, Дата рождения: » + crs.getDate(«дата_рождения»)); System.out.println(); > //Close resource crs.close(); >catch (SQLException se) se.printStackTrace(); >catch (Exception ex) ex.printStackTrace(); > >//end main public static void writeCachedRowSet() throws Exception //Instantiate a CachedRowSet object, set connection parameters OracleCachedRowSet crs = new OracleCachedRowSet(); crs.setUrl(«jdbc:oracle:thin:@localhost:1521:orbis»); crs.setUsername(«stud»); crs.setPassword(«stud»); //Set and execute the command. Notice the parameter query. String sql = «SELECT * FROM н_люди WHERE ид = ?»; crs.setCommand(sql); crs.setInt(1,123456); crs.execute(); //Serialize CachedRowSet object. FileOutputStream fos = new FileOutputStream(CRS_FILE_LOC); ObjectOutputStream out = new ObjectOutputStream(fos); out.writeObject(crs); out.close(); crs.close(); >//end writeCachedRowSet() public static OracleCachedRowSet readCachedRowSet() throws Exception //Read serialized CachedRowSet object from storage FileInputStream fis = new FileInputStream(CRS_FILE_LOC); ObjectInputStream in = new ObjectInputStream(fis); OracleCachedRowSet crs = (OracleCachedRowSet)in.readObject(); fis.close(); in.close(); return crs; >//end readCachedRowSet() >//end CachedRS

Для демонстрации использования объекта типа CachedRowSet при отсутствии соединения с базой данных в примере созданы два метода. Метод writeCachedRowSet() создает объект, заполняет его данными и сохраняет его. Метод readCachedRowSet() читает с диска сохраненный объект и возвращает его вызывающему методу. В реальных приложениях объекты сохраняются с использованием службы имен и каталогов посредством интерфейса JNDI. Для изучения этой возможности используйте в качестве службы имен и каталогов файловую систему (см. примеры предыдущего занятия) и самостоятельно модернизируйте приведенный выше пример.

Использование объектов типа CachedRowSet не ограничивается только просмотром данных. Можно изменять и удалять существующие строки, а так же добавлять новые. Объект типа CachedRowSet хранит в памяти и оригинальную и измененную копию данных и работает с ними при отсутствии соединения с базой. Для внесения изменений в базу из виртуальной таблицы объекта необходимо использование нового (не унаследованного от интерфейса ResultSet) метода – acceptChanges(). Вызов этого метода заставляет объект типа CachedRowSet соединиться с базой данных и внести в нее изменения. Если в процессе внесения изменений возникли ошибки, то выдается исключение SQLException. Ниже приведены примеры программного кода, иллюстрирующие эти возможности на данных таблиц, созданных на предыдущих занятиях.

//Populate a CachedRowSet object, crs String sql = «SELECT * FROM номера_телефонов WHERE ид_л = ?»; crs.setCommand(sql); crs.setInt(1,125704); crs.execute(); //Make rowset updatable crs.setReadOnly(false); //*** Update example //Move to first and only row and give myself a raise crs.first(); crs.updateString(2,»1131313″); //Signal changes are finished crs.updateRow(); //Write records to database crs.acceptChanges();

//*** Insert new row example //Move cursor to the insert row position crs.moveToInsertRow(); //Add the data for the new row crs.updateInt(1,120848); crs.updateString(2,»9332323″); crs.updateString(3,»1−1−02″); crs.updateInt(4,1); //write the rows to the rowset crs.insertRow(); //Submit the data to the data source crs.acceptChanges();

До тех пор, пока не выполнен метод acceptChanges(), можно «откатить» изменения данных, так как в объекте хранятся обе таблицы – и оригинальная (с исходными данными) и измененная. Для этого необходимо выполнить метод restoreOriginal(). Этот метод эквивалентен SQL-предложению ROLLBACK. Второй метод – cancelRowUpdates() — отменяет изменения, сделанные в текущей строке.

Для изучения указанных выше методов необходимо самостоятельно создать класс, демонстрирующий обновление существующих данных, добавление новых данных и отмену сделанных изменений, как полную, так и частичную.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *