Spec-Zone .ru
спецификации, руководства, описания, API
|
A CachedRowSet
объект является особенным в этом, он может работать, не будучи соединенным с его источником данных, то есть, это - разъединенный RowSet
объект. Это получает свое имя от факта, что это хранит (кэши) свои данные в памяти так, чтобы это могло работать на ее собственных данных, а не на данных, хранивших в базе данных.
CachedRowSet
интерфейс является суперинтерфейсом для всех разъединенных RowSet
объекты, таким образом, все демонстрировало здесь также, применяются к WebRowSet
, JoinRowSet
, и FilteredRowSet
объекты.
Отметьте что хотя источник данных для a CachedRowSet
объект (и RowSet
объекты, полученные из этого), почти всегда реляционная база данных, a CachedRowSet
объект способен к получению данных от любого источника данных, который хранит его данные в табличном формате. Например, плоский файл или электронная таблица могли быть источником данных. Это - истина когда RowSetReader
объект для разъединенного RowSet
объект реализуется, чтобы считать данные из такого источника данных. Ссылочная реализация CachedRowSet
у интерфейса есть a RowSetReader
возразите, что данные чтений от реляционной базы данных, таким образом, в этом учебном руководстве, источник данных всегда является базой данных.
Следующие темы затрагиваются:
Установка a CachedRowSet
объект включает следующее:
Можно создать новое CachedRowSet
объект различными способами:
RowSetFactory
, который создается из class RowSetProvider
: См. Используя Интерфейс RowSetFactory в Использовании Объектов JdbcRowSet для получения дополнительной информации.Отметьте: Альтернативно, можно использовать конструктора от CachedRowSet
реализация Вашего драйвера JDBC. Однако, реализации RowSet
интерфейс будет отличаться от ссылочной реализации. У этих реализаций будут различные имена и конструкторы. Например, Oracle реализация драйвера JDBC CachedRowSet
интерфейс называют oracle.jdbc.rowset.OracleCachedRowSet
.
Один из путей можно создать a CachedRowSet
объект, вызывая конструктора по умолчанию, определенного в ссылочной реализации, как делается в следующей строке кода:
CachedRowSet crs = new CachedRowSetImpl();
Объект crs
имеет те же самые значения по умолчанию для его свойств это a JdbcRowSet
объект имеет, когда он сначала создается. Кроме того, это было присвоено экземпляр значения по умолчанию SyncProvider
реализация, RIOptimisticProvider
.
A SyncProvider
возразите предоставляет a RowSetReader
объект (читатель) и a RowSetWriter
объект (писатель), который разъединенный RowSet
возразите потребностям, чтобы считать данные из его источника данных или записывать данные обратно к его источнику данных. Какой читатель и писатель делают объясняется позже в разделах, Что Делает Читатель и Что Делает Писатель. Одна вещь иметь в виду состоит в том, что читатели и писатели работают полностью в фоновом режиме, таким образом, объяснение того, как они работают, для Вашей информации только. Наличие некоторого фона на читателях и писателях должно помочь Вам понять что некоторые из методов, определенных в CachedRowSet
интерфейс делает в фоновом режиме.
Обычно, значения по умолчанию для свойств прекрасны, как они, но можно изменить значение свойства, вызывая соответствующий метод метода set. Есть некоторые свойства без значений по умолчанию, которые следует установить самостоятельно.
Чтобы получить данные, разъединенный RowSet
объект должен быть в состоянии соединиться с источником данных и иметь некоторые средства выбора данных, которые это должно содержать. Следующие свойства содержат информацию, необходимую, чтобы получить соединение с базой данных.
username
: Имя пользователь предоставляет к базе данных как часть получения доступаpassword
: Пароль базы данных пользователяurl
: URL JDBC для базы данных, с которой пользователь хочет соединитьсяdatasourceName
: Имя, используемое, чтобы получить объект DataSource, который был зарегистрирован в JNDI именование службыТо, который из этих свойств следует установить, зависит от того, как Вы собираетесь сделать соединение. Привилегированный путь состоит в том, чтобы использовать a DataSource
объект, но это, возможно, не практично для Вас, чтобы зарегистрировать a DataSource
объект с JNDI именование службы, которая обычно делается системным администратором. Поэтому, примеры кода все использование DriverManager
механизм, чтобы получить соединение, для которого Вы используете url
свойство а не datasourceName
свойство.
Следующие строки кодового набора username
, password
, и url
свойства так, чтобы соединение могло быть получено, используя DriverManager
class. (Вы найдете, что URL JDBC устанавливает как значение для url
свойство в документации для Вашего драйвера JDBC.)
public void setConnectionProperties( String username, String password) { crs.setUsername(username); crs.setPassword(password); crs.setUrl("jdbc:mySubprotocol:mySubname"); // ...
Другое свойство, которое следует установить, command
свойство. В ссылочной реализации данные читаются в a RowSet
объект от a ResultSet
объект. Запрос, который производит это ResultSet
объект является значением для command
свойство. Например, следующая строка кодовых наборов command
свойство с запросом, который производит a ResultSet
объект, содержащий все данные в таблице MERCH_INVENTORY
:
crs.setCommand("select * from MERCH_INVENTORY");
Если Вы идете, делают любые обновления к crs
возразите и хотите те обновления, сохраненные в базе данных, следует установить еще одну информацию: ключевые столбцы. Ключевые столбцы являются по существу тем же самым как первичным ключом, потому что они указывают на один или более столбцов, которые однозначно определяют строку. Различие - то, что первичный ключ устанавливается на таблице в базе данных, тогда как ключевые столбцы устанавливаются на детали RowSet
объект. Следующие строки кодового набора ключевые столбцы для crs
к первому столбцу:
int [] keys = {1}; crs.setKeyColumns(keys);
Первый столбец в таблице MERCH_INVENTORY
ITEM_ID
. Это может служить ключевым столбцом, потому что каждый идентификатор элемента отличается и поэтому однозначно определяет одну строку и только одну строку в таблице MERCH_INVENTORY
. Кроме того, этот столбец определяется как первичный ключ в определении MERCH_INVENTORY
таблица. Метод setKeyColumns
берет массив, чтобы учесть факт, что может потребоваться два или больше столбца, чтобы идентифицировать строку уникально.
Как интересное место, метод setKeyColumns
не устанавливает значение для свойства. В этом случае это устанавливает значение для поля keyCols
. Ключевые столбцы используются внутренне, таким образом, после установки их, Вы не делаете ничего больше с ними. Вы будете видеть, как и когда ключевые столбцы будут использоваться в разделе Используя Объекты SyncResolver.
Заполнение разъединенного RowSet
объект включает больше работы чем заполнение соединенного RowSet
объект. К счастью, дополнительная работа делается в фоновом режиме. После того, как Вы сделали предварительную работу, чтобы установить CachedRowSet
объект crs
, следующая строка кода заполняет crs
:
crs.execute();
Данные в crs
данные в ResultSet
объект, произведенный, выполняя запрос в свойстве команды.
То, что отличается, то, что CachedRowSet
реализация для execute
метод делает намного больше чем JdbcRowSet
реализация. Или более правильно, CachedRowSet
читатель объекта, в котором метод выполняют делегатов его задачи, делает намного больше.
Каждый разъединенный RowSet
у объекта есть a SyncProvider
объект, присвоенный этому, и это SyncProvider
объект состоит в том тем, что обеспечивает RowSet
читатель объекта (a RowSetReader
объект). Когда crs
объект создавался, он использовался в качестве значения по умолчанию CachedRowSetImpl
конструктор, который, в дополнение к установке значений по умолчанию для свойств, присваивает экземпляр RIOptimisticProvider
реализация как значение по умолчанию SyncProvider
объект.
Когда приложение вызывает метод execute
, разъединенный RowSet
читатель объекта работает негласно, чтобы заполнить RowSet
объект с данными. Недавно создаваемый CachedRowSet
объект не соединяется с источником данных и поэтому должен получить соединение с тем источником данных, чтобы получить данные от этого. Ссылочная реализация значения по умолчанию SyncProvider
объект (RIOptimisticProvider
) предоставляет читателю, который получает соединение при использовании набора значений для имени пользователя, пароля, и или URL JDBC или имя источника данных, какой бы ни был установлен позже. Затем читатель выполняет набор запроса для команды. Это читает данные в ResultSet
объект, произведенный запросом, заполняя CachedRowSet
объект с теми данными. Наконец, читатель закрывает соединение.
В сценарии Перерыва на кофе владелец хочет оптимизировать операции. Владелец решает иметь сотрудников в складе, вводят материально-технические ресурсы непосредственно в PDA (персональный цифровой секретарь), таким образом избегая, чтобы подверженный ошибкам процесс наличия второго человека сделал ввод данных. A CachedRowSet
объект идеален в этой ситуации, потому что это легко, сериализуемо, и может быть обновлено без соединения с источником данных.
Владелец сделает разработку приложений объединять в команду, создают инструмент GUI для PDA, который складские сотрудники будут использовать для того, чтобы ввести данные учета. Штаб создаст a CachedRowSet
объект, заполненный с таблицей, показывая текущие материально-технические ресурсы и, отправляет это использующий Интернет для PDA. Когда складской сотрудник вводит данные, используя инструмент GUI, инструмент добавляет каждую запись в массив, который CachedRowSet
объект будет использовать, чтобы выполнить обновления в фоновом режиме. После завершения материально-технических ресурсов PDA отсылают свои новые данные назад к штабу, где данные загружаются на основной сервер.
Этот раздел затрагивает следующие темы:
Обновление данных в a CachedRowSet
объект все равно как обновляет данные в a JdbcRowSet
объект. Например, следующий фрагмент кода от CachedRowSetSample.java
постепенно увеличивает значение в столбце QUAN
1 в строке, чей ITEM_ID
у столбца есть идентификатор элемента 12345
:
while (crs.next()) { System.out.println( "Found item " + crs.getInt("ITEM_ID") + ": " + crs.getString("ITEM_NAME")); if (crs.getInt("ITEM_ID") == 1235) { int currentQuantity = crs.getInt("QUAN") + 1; System.out.println("Updating quantity to " + currentQuantity); crs.updateInt("QUAN", currentQuantity + 1); crs.updateRow(); // Synchronizing the row // back to the DB crs.acceptChanges(con); }
Так же, как с обновлением значения столбца, кода для вставки и удаления строк в a CachedRowSet
объект является тем же самым что касается a JdbcRowSet
объект.
Следующая выборка от CachedRowSetSample.java
вставляет новую строку в CachedRowSet
объект crs
:
crs.moveToInsertRow(); crs.updateInt("ITEM_ID", newItemId); crs.updateString("ITEM_NAME", "TableCloth"); crs.updateInt("SUP_ID", 927); crs.updateInt("QUAN", 14); Calendar timeStamp; timeStamp = new GregorianCalendar(); timeStamp.set(2006, 4, 1); crs.updateTimestamp( "DATE_VAL", new Timestamp(timeStamp.getTimeInMillis())); crs.insertRow(); crs.moveToCurrentRow();
Если бы штаб решил прекратить снабжать определенный элемент, он, вероятно, удалил бы строку для того кофе непосредственно. Однако, в сценарии, у складского сотрудника, использующего PDA также, есть возможность удаления этого. Следующий фрагмент кода находит строку где значение в ITEM_ID
столбец 12345
и удаляет это из CachedRowSet
crs
:
while (crs.next()) { if (crs.getInt("ITEM_ID") == 12345) { crs.deleteRow(); break; } }
Есть существенное различие между произведением изменений в a JdbcRowSet
объект и производящие изменения в a CachedRowSet
объект. Поскольку a JdbcRowSet
объект соединяется с его источником данных, методами updateRow
, insertRow
, и deleteRow
может обновить обоих JdbcRowSet
возразите и источник данных. В случае разъединенного RowSet
объект, однако, эти методы обновляют данные, хранившие в CachedRowSet
память объекта, но не может влиять на источник данных. Разъединенный RowSet
объект должен вызвать метод acceptChanges
чтобы сохранить его изменения к источнику данных. В сценарии материально-технических ресурсов, назад в штабе, приложение вызовет метод acceptChanges
обновить базу данных с новыми значениями для столбца QUAN
.
crs.acceptChanges();
Как метод execute
, метод acceptChanges
делает его работу незримо. Принимая во внимание, что метод execute
делегирует его работу к RowSet
читатель объекта, метод acceptChanges
делегирует его задачи к RowSet
писатель объекта. В фоновом режиме писатель открывает соединение с базой данных, обновляет базу данных с изменениями, произведенными в RowSet
объект, и затем закрывает соединение.
Трудность состоит в том, что конфликт может возникнуть. Конфликт является ситуацией, в которой другая сторона обновила значение в базе данных, которая соответствует значению, которое было обновлено в a RowSet
объект. Какое значение должно сохраниться в базе данных? То, что делает писатель, когда есть конфликт, зависит от того, как он реализуется, и есть много возможностей. В одном конце спектра писатель даже не проверяет на конфликты и только пишет все изменения в базу данных. Дело обстоит так с RIXMLProvider
реализация, которая используется a WebRowSet
объект. С другой стороны, писатель гарантирует, что нет никаких конфликтов, устанавливая блокировки базы данных, которые препятствуют тому, чтобы другие произвели изменения.
Писатель для crs
объект является тем, обеспеченным значением по умолчанию SyncProvider
реализация, RIOptimisticProvider
. RIOPtimisticProvider
реализация получает свое имя от факта, что она использует модель оптимистичного параллелизма. Эта модель предполагает, что будут немногие, если таковые вообще имеются, конфликты и поэтому не устанавливают блокировок базы данных. Проверки писателя, чтобы видеть, есть ли какие-либо конфликты, и если нет ни одного, это пишет изменения, произведенные в crs
возразите против базы данных, и те изменения становятся персистентными. Если есть какие-либо конфликты, значение по умолчанию не должно записать новое RowSet
значения к базе данных.
В сценарии поведение значения по умолчанию работает очень хорошо. Поскольку никто в штабе, вероятно, не изменит значение в QUAN
столбец COF_INVENTORY
, не будет никаких конфликтов. В результате значения, в которые вводят crs
объект в складе будет записан базе данных и таким образом будет персистентным, который является желаемым результатом.
В других ситуациях, однако, для конфликтов возможно существовать. Размещать эти ситуации, RIOPtimisticProvider
реализация предоставляет возможность, которая позволяет Вам смотреть на значения в конфликте и решать, которые должны быть персистентными. Эта опция является использованием a SyncResolver
объект.
Когда писатель закончил искать конфликты и нашел один или больше, это создает a SyncResolver
объект, содержащий значения базы данных, которые вызвали конфликты. Затем, метод acceptChanges
броски a SyncProviderException
объект, который приложение может поймать и использовать, чтобы получить SyncResolver
объект. Следующие строки кода получают SyncResolver
объект resolver
:
try { crs.acceptChanges(); } catch (SyncProviderException spe) { SyncResolver resolver = spe.getSyncResolver(); }
Объект resolver
a RowSet
объект, который тиражируется crs
возразите за исключением того, что это содержит только значения в базе данных, которая вызвала конфликт. Все другие значения столбцов являются нулем.
С resolver
объект, можно выполнить итерации через его строки, чтобы определить местоположение значений, которые не являются нулем и являются поэтому значениями, которые вызвали конфликт. Затем можно определить местоположение значения в той же самой позиции в crs
возразите и сравните их. Следующий фрагмент кода получает resolver
и использование SyncResolver
метод nextConflict
выполнить итерации через строки, у которых есть конфликтные значения. Объект resolver
получает состояние каждого конфликтного значения, и если это UPDATE_ROW_CONFLICT
, подразумевать, что crs
делал попытку обновления, когда конфликт произошел, resolver
объект получает номер строки того значения. Затем код перемещает курсор для crs
возразите против той же самой строки. Затем, код находит столбец в той строке resolver
объект, который содержит конфликтное значение, которое будет значением, которое не является нулем. После получения значения в том столбце от обоих resolver
и crs
объекты, можно сравнить два и решить, какой Вы хотите стать персистентными. Наконец, кодовые наборы, которые оценивают в обоих crs
возразите и база данных, используя метод setResolvedValue
, как показано в следующем коде:
try { crs.acceptChanges(); } catch (SyncProviderException spe) { SyncResolver resolver = spe.getSyncResolver(); // value in crs Object crsValue; // value in the SyncResolver object Object resolverValue; // value to be persistent Object resolvedValue; while (resolver.nextConflict()) { if (resolver.getStatus() == SyncResolver.UPDATE_ROW_CONFLICT) { int row = resolver.getRow(); crs.absolute(row); int colCount = crs.getMetaData().getColumnCount(); for (int j = 1; j <= colCount; j++) { if (resolver.getConflictValue(j) != null) { crsValue = crs.getObject(j); resolverValue = resolver.getConflictValue(j); // ... // compare crsValue and // resolverValue to // determine the value to be // persistent resolvedValue = crsValue; resolver.setResolvedValue( j, resolvedValue); } } } } }
Быть компонентом JavaBeans означает это a RowSet
объект может уведомить другие компоненты, когда определенные вещи происходят с ним. Например, если данные в a RowSet
возразите изменениям, RowSet
объект может уведомить заинтересованные стороны того изменения. Хорошая вещь об этом механизме уведомления состоит в том, что, как прикладной программист, все, что необходимо сделать, добавляют или удаляют компоненты, которые будут уведомлены.
Этот раздел затрагивает следующие темы:
Слушатель для a RowSet
объект является компонентом, который реализует следующие методы от RowSetListener
интерфейс:
cursorMoved
: Определяет то, что слушатель сделает, во всяком случае, когда курсор в RowSet
объектные перемещения.rowChanged
: Определяет то, что слушатель сделает, во всяком случае, когда одно или более значений столбцов подряд изменились, строка была вставлена, или строка была удалена.rowSetChanged
: Определяет то, что слушатель сделает, во всяком случае, когда RowSet
объект был заполнен с новыми данными.Примером компонента, который мог бы хотеть быть слушателем, является a BarGraph
возразите что графики данные в a RowSet
объект. Поскольку данные изменяются, BarGraph
объект может обновить себя, чтобы отразить новые данные.
Как прикладной программист, единственная вещь следует сделать, чтобы использовать в своих интересах механизм уведомления, должен добавить или удалить слушателей. Следующая строка кода означает что каждый раз курсор для crs
перемещения объектов, значения в crs
изменяются, или crs
в целом получает новые данные, BarGraph
объект bar
будет уведомлен:
crs.addRowSetListener(bar);
Можно также остановить уведомления, удаляя слушателя, как делается в следующей строке кода:
crs.removeRowSetListener(bar);
Используя сценарий Перерыва на кофе, предположите, что штаб сверяется с базой данных периодически, чтобы получить последний прейскурант для кофе, которые это продает онлайн. В этом случае слушатель PriceList
объект priceList
на веб-сайте Перерыва на кофе, который должен реализовать RowSetListener
методы cursorMoved
, rowChanged
, и rowSetChanged
. Реализация cursorMoved
метод мог быть должен ничего не сделать, потому что позиция курсора не влияет priceList
объект. Реализации для rowChanged
и rowSetChanged
методы, с другой стороны, должны установить то, что изменения были произведены и обновление priceList
соответственно.
В ссылочной реализации, методы, которые вызывают любой из RowSet
события автоматически уведомляют всех зарегистрированных слушателей. Например, любой метод, который перемещает курсор также, вызывает метод cursorMoved
на каждом из слушателей. Точно так же метод execute
вызывает метод rowSetChanged
на всех слушателях, и acceptChanges
вызовы rowChanged
на всех слушателях.
Пример кода CachedRowSetSample.testCachedRowSet
демонстрирует, как данные могут быть отправлены в мелких кусочках.