Liking cljdoc? Tell your friends :D

javax.sql.rowset.BaseRowSet

An abstract class providing a RowSet object with its basic functionality. The basic functions include having properties and sending event notifications, which all JavaBeans™ components must implement.

1.0 Overview The BaseRowSet class provides the core functionality for all RowSet implementations, and all standard implementations may use this class in combination with one or more RowSet interfaces in order to provide a standard vendor-specific implementation. To clarify, all implementations must implement at least one of the RowSet interfaces (JdbcRowSet, CachedRowSet, JoinRowSet, FilteredRowSet, or WebRowSet). This means that any implementation that extends the BaseRowSet class must also implement one of the RowSet interfaces.

The BaseRowSet class provides the following:

Properties

Fields for storing current properties
Methods for getting and setting properties

Event notification

A complete set of setter methods for setting the parameters in a RowSet object's command

Streams

Fields for storing stream instances Constants for indicating the type of a stream

2.0 Setting Properties All rowsets maintain a set of properties, which will usually be set using a tool. The number and kinds of properties a rowset has will vary, depending on what the RowSet implementation does and how it gets its data. For example, rowsets that get their data from a ResultSet object need to set the properties that are required for making a database connection. If a RowSet object uses the DriverManager facility to make a connection, it needs to set a property for the JDBC URL that identifies the appropriate driver, and it needs to set the properties that give the user name and password. If, on the other hand, the rowset uses a DataSource object to make the connection, which is the preferred method, it does not need to set the property for the JDBC URL. Instead, it needs to set the property for the logical name of the data source along with the properties for the user name and password.

NOTE: In order to use a DataSource object for making a connection, the DataSource object must have been registered with a naming service that uses the Java Naming and Directory Interface™ (JNDI) API. This registration is usually done by a person acting in the capacity of a system administrator.

3.0 Setting the Command and Its Parameters When a rowset gets its data from a relational database, it executes a command (a query) that produces a ResultSet object. This query is the command that is set for the RowSet object's command property. The rowset populates itself with data by reading the data from the ResultSet object into itself. If the query contains placeholders for values to be set, the BaseRowSet setter methods are used to set these values. All setter methods allow these values to be set to null if required.

The following code fragment illustrates how the CachedRowSet™ object crs might have its command property set. Note that if a tool is used to set properties, this is the code that the tool would use.

crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" "WHERE CREDIT_LIMIT > ? AND REGION = ?");

In this example, the values for CREDIT_LIMIT and REGION are placeholder parameters, which are indicated with a question mark (?). The first question mark is placeholder parameter number 1, the second question mark is placeholder parameter number 2, and so on. Any placeholder parameters must be set with values before the query can be executed. To set these placeholder parameters, the BaseRowSet class provides a set of setter methods, similar to those provided by the PreparedStatement interface, for setting values of each data type. A RowSet object stores the parameter values internally, and its execute method uses them internally to set values for the placeholder parameters before it sends the command to the DBMS to be executed.

The following code fragment demonstrates setting the two parameters in the query from the previous example.

crs.setInt(1, 5000); crs.setString(2, "West"); If the execute method is called at this point, the query sent to the DBMS will be:

"SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" "WHERE CREDIT_LIMIT > 5000 AND REGION = 'West'" NOTE: Setting Array, Clob, Blob and Ref objects as a command parameter, stores these values as SerialArray, SerialClob, SerialBlob and SerialRef objects respectively.

4.0 Handling of Parameters Behind the Scenes

NOTE: The BaseRowSet class provides two kinds of setter methods, those that set properties and those that set placeholder parameters. The setter methods discussed in this section are those that set placeholder parameters.

The placeholder parameters set with the BaseRowSet setter methods are stored as objects in an internal Hashtable object. Primitives are stored as their Object type. For example, byte is stored as Byte object, and int is stored as an Integer object. When the method execute is called, the values in the Hashtable object are substituted for the appropriate placeholder parameters in the command.

A call to the method getParams returns the values stored in the Hashtable object as an array of Object instances. An element in this array may be a simple Object instance or an array (which is a type of Object). The particular setter method used determines whether an element in this array is an Object or an array.

The majority of methods for setting placeholder parameters take two parameters, with the first parameter indicating which placeholder parameter is to be set, and the second parameter giving the value to be set. Methods such as setInt, setString, setBoolean, and setLong fall into this category. After these methods have been called, a call to the method getParams will return an array with the values that have been set. Each element in the array is an Object instance representing the values that have been set. The order of these values in the array is determined by the int (the first parameter) passed to the setter method. The values in the array are the values (the second parameter) passed to the setter method. In other words, the first element in the array is the value to be set for the first placeholder parameter in the RowSet object's command. The second element is the value to be set for the second placeholder parameter, and so on.

Several setter methods send the driver and DBMS information beyond the value to be set. When the method getParams is called after one of these setter methods has been used, the elements in the array will themselves be arrays to accommodate the additional information. In this category, the method setNull is a special case because one version takes only two parameters (setNull(int parameterIndex, int SqlType)). Nevertheless, it requires an array to contain the information that will be passed to the driver and DBMS. The first element in this array is the value to be set, which is null, and the second element is the int supplied for sqlType, which indicates the type of SQL value that is being set to null. This information is needed by some DBMSs and is therefore required in order to ensure that applications are portable. The other version is intended to be used when the value to be set to null is a user-defined type. It takes three parameters (setNull(int parameterIndex, int sqlType, String typeName)) and also requires an array to contain the information to be passed to the driver and DBMS. The first two elements in this array are the same as for the first version of setNull. The third element, typeName, gives the SQL name of the user-defined type. As is true with the other setter methods, the number of the placeholder parameter to be set is indicated by an element's position in the array returned by getParams. So, for example, if the parameter supplied to setNull is 2, the second element in the array returned by getParams will be an array of two or three elements.

Some methods, such as setObject and setDate have versions that take more than two parameters, with the extra parameters giving information to the driver or the DBMS. For example, the methods setDate, setTime, and setTimestamp can take a Calendar object as their third parameter. If the DBMS does not store time zone information, the driver uses the Calendar object to construct the Date, Time, or Timestamp object being set. As is true with other methods that provide additional information, the element in the array returned by getParams is an array instead of a simple Object instance.

The methods setAsciiStream, setBinaryStream, setCharacterStream, and setUnicodeStream (which is deprecated, so applications should use getCharacterStream instead) take three parameters, so for them, the element in the array returned by getParams is also an array. What is different about these setter methods is that in addition to the information provided by parameters, the array contains one of the BaseRowSet constants indicating the type of stream being set.

NOTE: The method getParams is called internally by RowSet implementations extending this class; it is not normally called by an application programmer directly.

5.0 Event Notification The BaseRowSet class provides the event notification mechanism for rowsets. It contains the field listeners, methods for adding and removing listeners, and methods for notifying listeners of changes.

A listener is an object that has implemented the RowSetListener interface. If it has been added to a RowSet object's list of listeners, it will be notified when an event occurs on that RowSet object. Each listener's implementation of the RowSetListener methods defines what that object will do when it is notified that an event has occurred.

There are three possible events for a RowSet object:

the cursor moves an individual row is changed (updated, deleted, or inserted) the contents of the entire RowSet object are changed

The BaseRowSet method used for the notification indicates the type of event that has occurred. For example, the method notifyRowChanged indicates that a row has been updated, deleted, or inserted. Each of the notification methods creates a RowSetEvent object, which is supplied to the listener in order to identify the RowSet object on which the event occurred. What the listener does with this information, which may be nothing, depends on how it was implemented.

6.0 Default Behavior A default BaseRowSet object is initialized with many starting values.

The following is true of a default RowSet instance that extends the BaseRowSet class:

Has a scrollable cursor and does not show changes made by others. Is updatable. Does not show rows that have been deleted. Has no time limit for how long a driver may take to execute the RowSet object's command. Has no limit for the number of rows it may contain. Has no limit for the number of bytes a column may contain. NOTE: This limit applies only to columns that hold values of the following types: BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR. Will not see uncommitted data (make "dirty" reads). Has escape processing turned on. Has its connection's type map set to null. Has an empty Vector object for storing the values set for the placeholder parameters in the RowSet object's command.

If other values are desired, an application must set the property values explicitly. For example, the following line of code sets the maximum number of rows for the CachedRowSet object crs to 500.

crs.setMaxRows(500); Methods implemented in extensions of this BaseRowSet class must throw an SQLException object for any violation of the defined assertions. Also, if the extending class overrides and reimplements any BaseRowSet method and encounters connectivity or underlying data source issues, that method may in addition throw an SQLException object for that reason.

An abstract class providing a RowSet object with its basic functionality.
The basic functions include having properties and sending event notifications,
which all JavaBeans™ components must implement.

1.0 Overview
The BaseRowSet class provides the core functionality
for all RowSet implementations,
and all standard implementations may use this class in combination with
one or more RowSet interfaces in order to provide a standard
vendor-specific implementation.  To clarify, all implementations must implement
at least one of the RowSet interfaces (JdbcRowSet,
CachedRowSet, JoinRowSet, FilteredRowSet,
or WebRowSet). This means that any implementation that extends
the BaseRowSet class must also implement one of the RowSet
interfaces.

The BaseRowSet class provides the following:


Properties

    Fields for storing current properties
    Methods for getting and setting properties


Event notification

A complete set of setter methods for setting the parameters in a
     RowSet object's command

 Streams

 Fields for storing stream instances
 Constants for indicating the type of a stream




2.0 Setting Properties
All rowsets maintain a set of properties, which will usually be set using
a tool.  The number and kinds of properties a rowset has will vary,
depending on what the RowSet implementation does and how it gets
its data.  For example,
rowsets that get their data from a ResultSet object need to
set the properties that are required for making a database connection.
If a RowSet object uses the DriverManager facility to make a
connection, it needs to set a property for the JDBC URL that identifies the
appropriate driver, and it needs to set the properties that give the
user name and password.
If, on the other hand, the rowset uses a DataSource object
to make the connection, which is the preferred method, it does not need to
set the property for the JDBC URL.  Instead, it needs to set the property
for the logical name of the data source along with the properties for
the user name and password.

NOTE:  In order to use a DataSource object for making a
connection, the DataSource object must have been registered
with a naming service that uses the Java Naming and Directory
Interface™ (JNDI) API.  This registration
is usually done by a person acting in the capacity of a system administrator.

3.0 Setting the Command and Its Parameters
When a rowset gets its data from a relational database, it executes a command (a query)
that produces a ResultSet object.  This query is the command that is set
for the RowSet object's command property.  The rowset populates itself with data by reading the
data from the ResultSet object into itself. If the query
contains placeholders for values to be set, the BaseRowSet setter methods
are used to set these values. All setter methods allow these values to be set
to null if required.

The following code fragment illustrates how the
CachedRowSet™
object crs might have its command property set.  Note that if a
tool is used to set properties, this is the code that the tool would use.


   crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS"
                  "WHERE CREDIT_LIMIT > ? AND REGION = ?");

In this example, the values for CREDIT_LIMIT and
REGION are placeholder parameters, which are indicated with a
question mark (?).  The first question mark is placeholder parameter number
1, the second question mark is placeholder parameter number
2, and so on.  Any placeholder parameters must be set with
values before the query can be executed. To set these
placeholder parameters, the BaseRowSet class provides a set of setter
methods, similar to those provided by the PreparedStatement
interface, for setting values of each data type.  A RowSet object stores the
parameter values internally, and its execute method uses them internally
to set values for the placeholder parameters
before it sends the command to the DBMS to be executed.

The following code fragment demonstrates
setting the two parameters in the query from the previous example.


   crs.setInt(1, 5000);
   crs.setString(2, "West");
If the execute method is called at this point, the query
sent to the DBMS will be:


   "SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS"
                  "WHERE CREDIT_LIMIT > 5000 AND REGION = 'West'"
NOTE: Setting Array, Clob, Blob and
Ref objects as a command parameter, stores these values as
SerialArray, SerialClob, SerialBlob
and SerialRef objects respectively.

4.0 Handling of Parameters Behind the Scenes

NOTE: The BaseRowSet class provides two kinds of setter methods,
those that set properties and those that set placeholder parameters. The setter
methods discussed in this section are those that set placeholder parameters.

The placeholder parameters set with the BaseRowSet setter methods
are stored as objects in an internal Hashtable object.
Primitives are stored as their Object type. For example, byte
is stored as Byte object, and int is stored as
an Integer object.
When the method execute is called, the values in the
Hashtable object are substituted for the appropriate placeholder
parameters in the command.

A call to the method getParams returns the values stored in the
Hashtable object as an array of Object instances.
An element in this array may be a simple Object instance or an
array (which is a type of Object). The particular setter method used
determines whether an element in this array is an Object or an array.

The majority of methods for setting placeholder parameters take two parameters,
 with the first parameter
indicating which placeholder parameter is to be set, and the second parameter
giving the value to be set.  Methods such as setInt,
setString, setBoolean, and setLong fall into
this category.  After these methods have been called, a call to the method
getParams will return an array with the values that have been set. Each
element in the array is an Object instance representing the
values that have been set. The order of these values in the array is determined by the
int (the first parameter) passed to the setter method. The values in the
array are the values (the second parameter) passed to the setter method.
In other words, the first element in the array is the value
to be set for the first placeholder parameter in the RowSet object's
command. The second element is the value to
be set for the second placeholder parameter, and so on.

Several setter methods send the driver and DBMS information beyond the value to be set.
When the method getParams is called after one of these setter methods has
been used, the elements in the array will themselves be arrays to accommodate the
additional information. In this category, the method setNull is a special case
because one version takes only
two parameters (setNull(int parameterIndex, int SqlType)). Nevertheless,
it requires
an array to contain the information that will be passed to the driver and DBMS.  The first
element in this array is the value to be set, which is null, and the
second element is the int supplied for sqlType, which
indicates the type of SQL value that is being set to null. This information
is needed by some DBMSs and is therefore required in order to ensure that applications
are portable.
The other version is intended to be used when the value to be set to null
is a user-defined type. It takes three parameters
(setNull(int parameterIndex, int sqlType, String typeName)) and also
requires an array to contain the information to be passed to the driver and DBMS.
The first two elements in this array are the same as for the first version of
setNull.  The third element, typeName, gives the SQL name of
the user-defined type. As is true with the other setter methods, the number of the
placeholder parameter to be set is indicated by an element's position in the array
returned by getParams.  So, for example, if the parameter
supplied to setNull is 2, the second element in the array
returned by getParams will be an array of two or three elements.

Some methods, such as setObject and setDate have versions
that take more than two parameters, with the extra parameters giving information
to the driver or the DBMS. For example, the methods setDate,
setTime, and setTimestamp can take a Calendar
object as their third parameter.  If the DBMS does not store time zone information,
the driver uses the Calendar object to construct the Date,
Time, or Timestamp object being set. As is true with other
methods that provide additional information, the element in the array returned
by getParams is an array instead of a simple Object instance.

The methods setAsciiStream, setBinaryStream,
setCharacterStream, and setUnicodeStream (which is
deprecated, so applications should use getCharacterStream instead)
take three parameters, so for them, the element in the array returned by
getParams is also an array.  What is different about these setter
methods is that in addition to the information provided by parameters, the array contains
one of the BaseRowSet constants indicating the type of stream being set.

NOTE: The method getParams is called internally by
RowSet implementations extending this class; it is not normally called by an
application programmer directly.

5.0 Event Notification
The BaseRowSet class provides the event notification
mechanism for rowsets.  It contains the field
listeners, methods for adding and removing listeners, and
methods for notifying listeners of changes.

A listener is an object that has implemented the RowSetListener interface.
If it has been added to a RowSet object's list of listeners, it will be notified
 when an event occurs on that RowSet object.  Each listener's
implementation of the RowSetListener methods defines what that object
will do when it is notified that an event has occurred.

There are three possible events for a RowSet object:

the cursor moves
an individual row is changed (updated, deleted, or inserted)
the contents of the entire RowSet object  are changed


The BaseRowSet method used for the notification indicates the
type of event that has occurred.  For example, the method
notifyRowChanged indicates that a row has been updated,
deleted, or inserted.  Each of the notification methods creates a
RowSetEvent object, which is supplied to the listener in order to
identify the RowSet object on which the event occurred.
What the listener does with this information, which may be nothing, depends on how it was
implemented.

6.0 Default Behavior
A default BaseRowSet object is initialized with many starting values.

The following is true of a default RowSet instance that extends
the BaseRowSet class:

  Has a scrollable cursor and does not show changes
      made by others.
  Is updatable.
  Does not show rows that have been deleted.
  Has no time limit for how long a driver may take to
      execute the RowSet object's command.
  Has no limit for the number of rows it may contain.
  Has no limit for the number of bytes a column may contain. NOTE: This
  limit applies only to columns that hold values of the
  following types:  BINARY, VARBINARY,
  LONGVARBINARY, CHAR, VARCHAR,
  and LONGVARCHAR.
  Will not see uncommitted data (make "dirty" reads).
  Has escape processing turned on.
  Has its connection's type map set to null.
  Has an empty Vector object for storing the values set
      for the placeholder parameters in the RowSet object's command.


If other values are desired, an application must set the property values
explicitly. For example, the following line of code sets the maximum number
of rows for the CachedRowSet object crs to 500.


   crs.setMaxRows(500);
Methods implemented in extensions of this BaseRowSet class must throw an
SQLException object for any violation of the defined assertions.  Also, if the
extending class overrides and reimplements any BaseRowSet method and encounters
connectivity or underlying data source issues, that method may in addition throw an
SQLException object for that reason.
raw docstring

javax.sql.rowset.CachedRowSet

The interface that all standard implementations of CachedRowSet must implement.

The reference implementation of the CachedRowSet interface provided by Oracle Corporation is a standard implementation. Developers may use this implementation just as it is, they may extend it, or they may choose to write their own implementations of this interface.

A CachedRowSet object is a container for rows of data that caches its rows in memory, which makes it possible to operate without always being connected to its data source. Further, it is a JavaBeans™ component and is scrollable, updatable, and serializable. A CachedRowSet object typically contains rows from a result set, but it can also contain rows from any file with a tabular format, such as a spread sheet. The reference implementation supports getting data only from a ResultSet object, but developers can extend the SyncProvider implementations to provide access to other tabular data sources.

An application can modify the data in a CachedRowSet object, and those modifications can then be propagated back to the source of the data.

A CachedRowSet object is a disconnected rowset, which means that it makes use of a connection to its data source only briefly. It connects to its data source while it is reading data to populate itself with rows and again while it is propagating changes back to its underlying data source. The rest of the time, a CachedRowSet object is disconnected, including while its data is being modified. Being disconnected makes a RowSet object much leaner and therefore much easier to pass to another component. For example, a disconnected RowSet object can be serialized and passed over the wire to a thin client such as a personal digital assistant (PDA).

1.0 Creating a CachedRowSet Object The following line of code uses the default constructor for CachedRowSet supplied in the reference implementation (RI) to create a default CachedRowSet object.

CachedRowSetImpl crs = new CachedRowSetImpl();

This new CachedRowSet object will have its properties set to the default properties of a BaseRowSet object, and, in addition, it will have an RIOptimisticProvider object as its synchronization provider. RIOptimisticProvider, one of two SyncProvider implementations included in the RI, is the default provider that the SyncFactory singleton will supply when no synchronization provider is specified.

A SyncProvider object provides a CachedRowSet object with a reader (a RowSetReader object) for reading data from a data source to populate itself with data. A reader can be implemented to read data from a ResultSet object or from a file with a tabular format. A SyncProvider object also provides a writer (a RowSetWriter object) for synchronizing any modifications to the CachedRowSet object's data made while it was disconnected with the data in the underlying data source.

A writer can be implemented to exercise various degrees of care in checking for conflicts and in avoiding them. (A conflict occurs when a value in the data source has been changed after the rowset populated itself with that value.) The RIOptimisticProvider implementation assumes there will be few or no conflicts and therefore sets no locks. It updates the data source with values from the CachedRowSet object only if there are no conflicts. Other writers can be implemented so that they always write modified data to the data source, which can be accomplished either by not checking for conflicts or, on the other end of the spectrum, by setting locks sufficient to prevent data in the data source from being changed. Still other writer implementations can be somewhere in between.

A CachedRowSet object may use any SyncProvider implementation that has been registered with the SyncFactory singleton. An application can find out which SyncProvider implementations have been registered by calling the following line of code.

 java.util.Enumeration providers = SyncFactory.getRegisteredProviders();

There are two ways for a CachedRowSet object to specify which SyncProvider object it will use.

Supplying the name of the implementation to the constructor
The following line of code creates the CachedRowSet
object crs2 that is initialized with default values except that its
SyncProvider object is the one specified.


     CachedRowSetImpl crs2 = new CachedRowSetImpl(
                            "com.fred.providers.HighAvailabilityProvider");
Setting the SyncProvider using the CachedRowSet
    method setSyncProvider
 The following line of code resets the SyncProvider object
 for crs, the CachedRowSet object created with the
 default constructor.


      crs.setSyncProvider("com.fred.providers.HighAvailabilityProvider");

See the comments for SyncFactory and SyncProvider for more details.

2.0 Retrieving Data from a CachedRowSet Object Data is retrieved from a CachedRowSet object by using the getter methods inherited from the ResultSet interface. The following examples, in which crs is a CachedRowSet object, demonstrate how to iterate through the rows, retrieving the column values in each row. The first example uses the version of the getter methods that take a column number; the second example uses the version that takes a column name. Column numbers are generally used when the RowSet object's command is of the form SELECT * FROM TABLENAME; column names are most commonly used when the command specifies columns by name.

while (crs.next()) { String name = crs.getString(1); int id = crs.getInt(2); Clob comment = crs.getClob(3); short dept = crs.getShort(4); System.out.println(name " " id " " comment " " dept); }

while (crs.next()) { String name = crs.getString("NAME"); int id = crs.getInt("ID"); Clob comment = crs.getClob("COM"); short dept = crs.getShort("DEPT"); System.out.println(name " " id " " comment " " dept); } 2.1 Retrieving RowSetMetaData An application can get information about the columns in a CachedRowSet object by calling ResultSetMetaData and RowSetMetaData methods on a RowSetMetaData object. The following code fragment, in which crs is a CachedRowSet object, illustrates the process. The first line creates a RowSetMetaData object with information about the columns in crs. The method getMetaData, inherited from the ResultSet interface, returns a ResultSetMetaData object, which is cast to a RowSetMetaData object before being assigned to the variable rsmd. The second line finds out how many columns jrs has, and the third line gets the JDBC type of values stored in the second column of jrs.

RowSetMetaData rsmd = (RowSetMetaData)crs.getMetaData();
int count = rsmd.getColumnCount();
int type = rsmd.getColumnType(2);

The RowSetMetaData interface differs from the ResultSetMetaData interface in two ways.

It includes setter methods: A RowSet object uses these methods internally when it is populated with data from a different ResultSet object.

It contains fewer getter methods: Some ResultSetMetaData methods to not apply to a RowSet object. For example, methods retrieving whether a column value is writable or read only do not apply because all of a RowSet object's columns will be writable or read only, depending on whether the rowset is updatable or not.

NOTE: In order to return a RowSetMetaData object, implementations must override the getMetaData() method defined in java.sql.ResultSet and return a RowSetMetaData object.

3.0 Updating a CachedRowSet Object Updating a CachedRowSet object is similar to updating a ResultSet object, but because the rowset is not connected to its data source while it is being updated, it must take an additional step to effect changes in its underlying data source. After calling the method updateRow or insertRow, a CachedRowSet object must also call the method acceptChanges to have updates written to the data source. The following example, in which the cursor is on a row in the CachedRowSet object crs, shows the code required to update two column values in the current row and also update the RowSet object's underlying data source.

crs.updateShort(3, 58);
crs.updateInt(4, 150000);
crs.updateRow();
crs.acceptChanges();

The next example demonstrates moving to the insert row, building a new row on the insert row, inserting it into the rowset, and then calling the method acceptChanges to add the new row to the underlying data source. Note that as with the getter methods, the updater methods may take either a column index or a column name to designate the column being acted upon.

crs.moveToInsertRow();
crs.updateString("Name", "Shakespeare");
crs.updateInt("ID", 10098347);
crs.updateShort("Age", 58);
crs.updateInt("Sal", 150000);
crs.insertRow();
crs.moveToCurrentRow();
crs.acceptChanges();

NOTE: Where the insertRow() method inserts the contents of a CachedRowSet object's insert row is implementation-defined. The reference implementation for the CachedRowSet interface inserts a new row immediately following the current row, but it could be implemented to insert new rows in any number of other places.

Another thing to note about these examples is how they use the method acceptChanges. It is this method that propagates changes in a CachedRowSet object back to the underlying data source, calling on the RowSet object's writer internally to write changes to the data source. To do this, the writer has to incur the expense of establishing a connection with that data source. The preceding two code fragments call the method acceptChanges immediately after calling updateRow or insertRow. However, when there are multiple rows being changed, it is more efficient to call acceptChanges after all calls to updateRow and insertRow have been made. If acceptChanges is called only once, only one connection needs to be established.

4.0 Updating the Underlying Data Source When the method acceptChanges is executed, the CachedRowSet object's writer, a RowSetWriterImpl object, is called behind the scenes to write the changes made to the rowset to the underlying data source. The writer is implemented to make a connection to the data source and write updates to it.

A writer is made available through an implementation of the SyncProvider interface, as discussed in section 1, "Creating a CachedRowSet Object." The default reference implementation provider, RIOptimisticProvider, has its writer implemented to use an optimistic concurrency control mechanism. That is, it maintains no locks in the underlying database while the rowset is disconnected from the database and simply checks to see if there are any conflicts before writing data to the data source. If there are any conflicts, it does not write anything to the data source.

The reader/writer facility provided by the SyncProvider class is pluggable, allowing for the customization of data retrieval and updating. If a different concurrency control mechanism is desired, a different implementation of SyncProvider can be plugged in using the method setSyncProvider.

In order to use the optimistic concurrency control routine, the RIOptismisticProvider maintains both its current value and its original value (the value it had immediately preceding the current value). Note that if no changes have been made to the data in a RowSet object, its current values and its original values are the same, both being the values with which the RowSet object was initially populated. However, once any values in the RowSet object have been changed, the current values and the original values will be different, though at this stage, the original values are still the initial values. With any subsequent changes to data in a RowSet object, its original values and current values will still differ, but its original values will be the values that were previously the current values.

Keeping track of original values allows the writer to compare the RowSet object's original value with the value in the database. If the values in the database differ from the RowSet object's original values, which means that the values in the database have been changed, there is a conflict. Whether a writer checks for conflicts, what degree of checking it does, and how it handles conflicts all depend on how it is implemented.

5.0 Registering and Notifying Listeners Being JavaBeans components, all rowsets participate in the JavaBeans event model, inheriting methods for registering listeners and notifying them of changes from the BaseRowSet class. A listener for a CachedRowSet object is a component that wants to be notified whenever there is a change in the rowset. For example, if a CachedRowSet object contains the results of a query and those results are being displayed in, say, a table and a bar graph, the table and bar graph could be registered as listeners with the rowset so that they can update themselves to reflect changes. To become listeners, the table and bar graph classes must implement the RowSetListener interface. Then they can be added to the CachedRowSet object's list of listeners, as is illustrated in the following lines of code.

crs.addRowSetListener(table); crs.addRowSetListener(barGraph); Each CachedRowSet method that moves the cursor or changes data also notifies registered listeners of the changes, so table and barGraph will be notified when there is a change in crs.

6.0 Passing Data to Thin Clients One of the main reasons to use a CachedRowSet object is to pass data between different components of an application. Because it is serializable, a CachedRowSet object can be used, for example, to send the result of a query executed by an enterprise JavaBeans component running in a server environment over a network to a client running in a web browser.

While a CachedRowSet object is disconnected, it can be much leaner than a ResultSet object with the same data. As a result, it can be especially suitable for sending data to a thin client such as a PDA, where it would be inappropriate to use a JDBC driver due to resource limitations or security considerations. Thus, a CachedRowSet object provides a means to "get rows in" without the need to implement the full JDBC API.

7.0 Scrolling and Updating A second major use for CachedRowSet objects is to provide scrolling and updating for ResultSet objects that do not provide these capabilities themselves. In other words, a CachedRowSet object can be used to augment the capabilities of a JDBC technology-enabled driver (hereafter called a "JDBC driver") when the DBMS does not provide full support for scrolling and updating. To achieve the effect of making a non-scrollble and read-only ResultSet object scrollable and updatable, a programmer simply needs to create a CachedRowSet object populated with that ResultSet object's data. This is demonstrated in the following code fragment, where stmt is a Statement object.

ResultSet rs = stmt.executeQuery("SELECT * FROM EMPLOYEES"); CachedRowSetImpl crs = new CachedRowSetImpl(); crs.populate(rs);

The object crs now contains the data from the table EMPLOYEES, just as the object rs does. The difference is that the cursor for crs can be moved forward, backward, or to a particular row even if the cursor for rs can move only forward. In addition, crs is updatable even if rs is not because by default, a CachedRowSet object is both scrollable and updatable.

In summary, a CachedRowSet object can be thought of as simply a disconnected set of rows that are being cached outside of a data source. Being thin and serializable, it can easily be sent across a wire, and it is well suited to sending data to a thin client. However, a CachedRowSet object does have a limitation: It is limited in size by the amount of data it can store in memory at one time.

8.0 Getting Universal Data Access Another advantage of the CachedRowSet class is that it makes it possible to retrieve and store data from sources other than a relational database. The reader for a rowset can be implemented to read and populate its rowset with data from any tabular data source, including a spreadsheet or flat file. Because both a CachedRowSet object and its metadata can be created from scratch, a component that acts as a factory for rowsets can use this capability to create a rowset containing data from non-SQL data sources. Nevertheless, it is expected that most of the time, CachedRowSet objects will contain data that was fetched from an SQL database using the JDBC API.

9.0 Setting Properties All rowsets maintain a set of properties, which will usually be set using a tool. The number and kinds of properties a rowset has will vary, depending on what the rowset does and how it gets its data. For example, rowsets that get their data from a ResultSet object need to set the properties that are required for making a database connection. If a rowset uses the DriverManager facility to make a connection, it needs to set a property for the JDBC URL that identifies the appropriate driver, and it needs to set the properties that give the user name and password. If, on the other hand, the rowset uses a DataSource object to make the connection, which is the preferred method, it does not need to set the property for the JDBC URL. Instead, it needs to set properties for the logical name of the data source, for the user name, and for the password.

NOTE: In order to use a DataSource object for making a connection, the DataSource object must have been registered with a naming service that uses the Java Naming and Directory Interface™ (JNDI) API. This registration is usually done by a person acting in the capacity of a system administrator.

In order to be able to populate itself with data from a database, a rowset needs to set a command property. This property is a query that is a PreparedStatement object, which allows the query to have parameter placeholders that are set at run time, as opposed to design time. To set these placeholder parameters with values, a rowset provides setter methods for setting values of each data type, similar to the setter methods provided by the PreparedStatement interface.

The following code fragment illustrates how the CachedRowSet object crs might have its command property set. Note that if a tool is used to set properties, this is the code that the tool would use.

crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS " "WHERE CREDIT_LIMIT > ? AND REGION = ?");

The values that will be used to set the command's placeholder parameters are contained in the RowSet object's params field, which is a Vector object. The CachedRowSet class provides a set of setter methods for setting the elements in its params field. The following code fragment demonstrates setting the two parameters in the query from the previous example.

crs.setInt(1, 5000); crs.setString(2, "West");

The params field now contains two elements, each of which is an array two elements long. The first element is the parameter number; the second is the value to be set. In this case, the first element of params is 1, 5000, and the second element is 2, "West". When an application calls the method execute, it will in turn call on this RowSet object's reader, which will in turn invoke its readData method. As part of its implementation, readData will get the values in params and use them to set the command's placeholder parameters. The following code fragment gives an idea of how the reader does this, after obtaining the Connection object con.

PreparedStatement pstmt = con.prepareStatement(crs.getCommand()); reader.decodeParams(); // decodeParams figures out which setter methods to use and does something // like the following: // for (i = 0; i < params.length; i++) { // pstmt.setObject(i 1, params[i]); // }

At this point, the command for crs is the query "SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS WHERE CREDIT_LIMIT > 5000 AND REGION = "West". After the readData method executes this command with the following line of code, it will have the data from rs with which to populate crs.

ResultSet rs = pstmt.executeQuery();

The preceding code fragments give an idea of what goes on behind the scenes; they would not appear in an application, which would not invoke methods like readData and decodeParams. In contrast, the following code fragment shows what an application might do. It sets the rowset's command, sets the command's parameters, and executes the command. Simply by calling the execute method, crs populates itself with the requested data from the table CUSTOMERS.

crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" "WHERE CREDIT_LIMIT > ? AND REGION = ?"); crs.setInt(1, 5000); crs.setString(2, "West"); crs.execute();

10.0 Paging Data Because a CachedRowSet object stores data in memory, the amount of data that it can contain at any one time is determined by the amount of memory available. To get around this limitation, a CachedRowSet object can retrieve data from a ResultSet object in chunks of data, called pages. To take advantage of this mechanism, an application sets the number of rows to be included in a page using the method setPageSize. In other words, if the page size is set to five, a chunk of five rows of data will be fetched from the data source at one time. An application can also optionally set the maximum number of rows that may be fetched at one time. If the maximum number of rows is set to zero, or no maximum number of rows is set, there is no limit to the number of rows that may be fetched at a time.

After properties have been set, the CachedRowSet object must be populated with data using either the method populate or the method execute. The following lines of code demonstrate using the method populate. Note that this version of the method takes two parameters, a ResultSet handle and the row in the ResultSet object from which to start retrieving rows.

CachedRowSet crs = new CachedRowSetImpl();
crs.setMaxRows(20);
crs.setPageSize(4);
crs.populate(rsHandle, 10);

When this code runs, crs will be populated with four rows from rsHandle starting with the tenth row.

The next code fragment shows populating a CachedRowSet object using the method execute, which may or may not take a Connection object as a parameter. This code passes execute the Connection object conHandle.

Note that there are two differences between the following code fragment and the previous one. First, the method setMaxRows is not called, so there is no limit set for the number of rows that crs may contain. (Remember that crs always has the overriding limit of how much data it can store in memory.) The second difference is that the you cannot pass the method execute the number of the row in the ResultSet object from which to start retrieving rows. This method always starts with the first row.

CachedRowSet crs = new CachedRowSetImpl();
crs.setPageSize(5);
crs.execute(conHandle);

After this code has run, crs will contain five rows of data from the ResultSet object produced by the command for crs. The writer for crs will use conHandle to connect to the data source and execute the command for crs. An application is then able to operate on the data in crs in the same way that it would operate on data in any other CachedRowSet object.

To access the next page (chunk of data), an application calls the method nextPage. This method creates a new CachedRowSet object and fills it with the next page of data. For example, assume that the CachedRowSet object's command returns a ResultSet object rs with 1000 rows of data. If the page size has been set to 100, the first call to the method nextPage will create a CachedRowSet object containing the first 100 rows of rs. After doing what it needs to do with the data in these first 100 rows, the application can again call the method nextPage to create another CachedRowSet object with the second 100 rows from rs. The data from the first CachedRowSet object will no longer be in memory because it is replaced with the data from the second CachedRowSet object. After the tenth call to the method nextPage, the tenth CachedRowSet object will contain the last 100 rows of data from rs, which are stored in memory. At any given time, the data from only one CachedRowSet object is stored in memory.

The method nextPage returns true as long as the current page is not the last page of rows and false when there are no more pages. It can therefore be used in a while loop to retrieve all of the pages, as is demonstrated in the following lines of code.

CachedRowSet crs = CachedRowSetImpl();
crs.setPageSize(100);
crs.execute(conHandle);

while(crs.nextPage()) {
    while(crs.next()) {
        . . . // operate on chunks (of 100 rows each) in crs,
              // row by row
    }
}

After this code fragment has been run, the application will have traversed all 1000 rows, but it will have had no more than 100 rows in memory at a time.

The CachedRowSet interface also defines the method previousPage. Just as the method nextPage is analogous to the ResultSet method next, the method previousPage is analogous to the ResultSet method previous. Similar to the method nextPage, previousPage creates a CachedRowSet object containing the number of rows set as the page size. So, for instance, the method previousPage could be used in a while loop at the end of the preceding code fragment to navigate back through the pages from the last page to the first page. The method previousPage is also similar to nextPage in that it can be used in a while loop, except that it returns true as long as there is another page preceding it and false when there are no more pages ahead of it.

By positioning the cursor after the last row for each page, as is done in the following code fragment, the method previous navigates from the last row to the first row in each page. The code could also have left the cursor before the first row on each page and then used the method next in a while loop to navigate each page from the first row to the last row.

The following code fragment assumes a continuation from the previous code fragment, meaning that the cursor for the tenth CachedRowSet object is on the last row. The code moves the cursor to after the last row so that the first call to the method previous will put the cursor back on the last row. After going through all of the rows in the last page (the CachedRowSet object crs), the code then enters the while loop to get to the ninth page, go through the rows backwards, go to the eighth page, go through the rows backwards, and so on to the first row of the first page.

crs.afterLast();
while(crs.previous())  {
    . . . // navigate through the rows, last to first
{
while(crs.previousPage())  {
    crs.afterLast();
    while(crs.previous())  {
        . . . // go from the last row to the first row of each page
    }
}
The interface that all standard implementations of
CachedRowSet must implement.

The reference implementation of the CachedRowSet interface provided
by Oracle Corporation is a standard implementation. Developers may use this implementation
just as it is, they may extend it, or they may choose to write their own implementations
of this interface.

A CachedRowSet object is a container for rows of data
that caches its rows in memory, which makes it possible to operate without always being
connected to its data source. Further, it is a
JavaBeans™ component and is scrollable,
updatable, and serializable. A CachedRowSet object typically
contains rows from a result set, but it can also contain rows from any file
with a tabular format, such as a spread sheet.  The reference implementation
supports getting data only from a ResultSet object, but
developers can extend the SyncProvider implementations to provide
access to other tabular data sources.

An application can modify the data in a CachedRowSet object, and
those modifications can then be propagated back to the source of the data.

A CachedRowSet object is a disconnected rowset, which means
that it makes use of a connection to its data source only briefly. It connects to its
data source while it is reading data to populate itself with rows and again
while it is propagating changes back to its underlying data source. The rest
of the time, a CachedRowSet object is disconnected, including
while its data is being modified. Being disconnected makes a RowSet
object much leaner and therefore much easier to pass to another component.  For
example, a disconnected RowSet object can be serialized and passed
over the wire to a thin client such as a personal digital assistant (PDA).


1.0 Creating a CachedRowSet Object
The following line of code uses the default constructor for
CachedRowSet
supplied in the reference implementation (RI) to create a default
CachedRowSet object.


    CachedRowSetImpl crs = new CachedRowSetImpl();
This new CachedRowSet object will have its properties set to the
default properties of a BaseRowSet object, and, in addition, it will
have an RIOptimisticProvider object as its synchronization provider.
RIOptimisticProvider, one of two SyncProvider
implementations included in the RI, is the default provider that the
SyncFactory singleton will supply when no synchronization
provider is specified.

A SyncProvider object provides a CachedRowSet object
with a reader (a RowSetReader object) for reading data from a
data source to populate itself with data. A reader can be implemented to read
data from a ResultSet object or from a file with a tabular format.
A SyncProvider object also provides
a writer (a RowSetWriter object) for synchronizing any
modifications to the CachedRowSet object's data made while it was
disconnected with the data in the underlying data source.

A writer can be implemented to exercise various degrees of care in checking
for conflicts and in avoiding them.
(A conflict occurs when a value in the data source has been changed after
the rowset populated itself with that value.)
The RIOptimisticProvider implementation assumes there will be
few or no conflicts and therefore sets no locks. It updates the data source
with values from the CachedRowSet object only if there are no
conflicts.
Other writers can be implemented so that they always write modified data to
the data source, which can be accomplished either by not checking for conflicts
or, on the other end of the spectrum, by setting locks sufficient to prevent data
in the data source from being changed. Still other writer implementations can be
somewhere in between.

A CachedRowSet object may use any
SyncProvider implementation that has been registered
with the SyncFactory singleton. An application
can find out which SyncProvider implementations have been
registered by calling the following line of code.


     java.util.Enumeration providers = SyncFactory.getRegisteredProviders();

There are two ways for a CachedRowSet object to specify which
SyncProvider object it will use.

    Supplying the name of the implementation to the constructor
    The following line of code creates the CachedRowSet
    object crs2 that is initialized with default values except that its
    SyncProvider object is the one specified.


         CachedRowSetImpl crs2 = new CachedRowSetImpl(
                                "com.fred.providers.HighAvailabilityProvider");
    Setting the SyncProvider using the CachedRowSet
        method setSyncProvider
     The following line of code resets the SyncProvider object
     for crs, the CachedRowSet object created with the
     default constructor.


          crs.setSyncProvider("com.fred.providers.HighAvailabilityProvider");

See the comments for SyncFactory and SyncProvider for
more details.


2.0 Retrieving Data from a CachedRowSet Object
Data is retrieved from a CachedRowSet object by using the
getter methods inherited from the ResultSet
interface.  The following examples, in which crs is a
CachedRowSet
object, demonstrate how to iterate through the rows, retrieving the column
values in each row.  The first example uses the version of the
getter methods that take a column number; the second example
uses the version that takes a column name. Column numbers are generally
used when the RowSet object's command
is of the form SELECT * FROM TABLENAME; column names are most
commonly used when the command specifies columns by name.


   while (crs.next()) {
       String name = crs.getString(1);
       int id = crs.getInt(2);
       Clob comment = crs.getClob(3);
       short dept = crs.getShort(4);
       System.out.println(name  "  "  id  "  "  comment  "  "  dept);
   }



   while (crs.next()) {
       String name = crs.getString("NAME");
       int id = crs.getInt("ID");
       Clob comment = crs.getClob("COM");
       short dept = crs.getShort("DEPT");
       System.out.println(name  "  "  id  "  "  comment  "  "  dept);
   }
2.1 Retrieving RowSetMetaData
An application can get information about the columns in a CachedRowSet
object by calling ResultSetMetaData and RowSetMetaData
methods on a RowSetMetaData object. The following code fragment,
in which crs is a CachedRowSet object, illustrates the process.
The first line creates a RowSetMetaData object with information
about the columns in crs.  The method getMetaData,
inherited from the ResultSet interface, returns a
ResultSetMetaData object, which is cast to a
RowSetMetaData object before being assigned to the variable
rsmd.  The second line finds out how many columns jrs has, and
the third line gets the JDBC type of values stored in the second column of
jrs.


    RowSetMetaData rsmd = (RowSetMetaData)crs.getMetaData();
    int count = rsmd.getColumnCount();
    int type = rsmd.getColumnType(2);
The RowSetMetaData interface differs from the
ResultSetMetaData interface in two ways.

  It includes setter methods: A RowSet
  object uses these methods internally when it is populated with data from a
  different ResultSet object.

  It contains fewer getter methods: Some
  ResultSetMetaData methods to not apply to a RowSet
  object. For example, methods retrieving whether a column value is writable
  or read only do not apply because all of a RowSet object's
  columns will be writable or read only, depending on whether the rowset is
  updatable or not.

NOTE: In order to return a RowSetMetaData object, implementations must
override the getMetaData() method defined in
java.sql.ResultSet and return a RowSetMetaData object.

3.0 Updating a CachedRowSet Object
Updating a CachedRowSet object is similar to updating a
ResultSet object, but because the rowset is not connected to
its data source while it is being updated, it must take an additional step
to effect changes in its underlying data source. After calling the method
updateRow or insertRow, a
CachedRowSet
object must also call the method acceptChanges to have updates
written to the data source. The following example, in which the cursor is
on a row in the CachedRowSet object crs, shows
the code required to update two column values in the current row and also
update the RowSet object's underlying data source.


    crs.updateShort(3, 58);
    crs.updateInt(4, 150000);
    crs.updateRow();
    crs.acceptChanges();

The next example demonstrates moving to the insert row, building a new
row on the insert row, inserting it into the rowset, and then calling the
method acceptChanges to add the new row to the underlying data
source.  Note that as with the getter methods, the  updater methods may take
either a column index or a column name to designate the column being acted upon.


    crs.moveToInsertRow();
    crs.updateString("Name", "Shakespeare");
    crs.updateInt("ID", 10098347);
    crs.updateShort("Age", 58);
    crs.updateInt("Sal", 150000);
    crs.insertRow();
    crs.moveToCurrentRow();
    crs.acceptChanges();

NOTE: Where the insertRow() method inserts the contents of a
CachedRowSet object's insert row is implementation-defined.
The reference implementation for the CachedRowSet interface
inserts a new row immediately following the current row, but it could be
implemented to insert new rows in any number of other places.

Another thing to note about these examples is how they use the method
acceptChanges.  It is this method that propagates changes in
a CachedRowSet object back to the underlying data source,
calling on the RowSet object's writer internally to write
changes to the data source. To do this, the writer has to incur the expense
of establishing a connection with that data source. The
preceding two code fragments call the method acceptChanges
immediately after calling updateRow or insertRow.
However, when there are multiple rows being changed, it is more efficient to call
acceptChanges after all calls to updateRow
and insertRow have been made.  If acceptChanges
is called only once, only one connection needs to be established.

4.0 Updating the Underlying Data Source
When the method acceptChanges is executed, the
CachedRowSet object's writer, a RowSetWriterImpl
object, is called behind the scenes to write the changes made to the
rowset to the underlying data source. The writer is implemented to make a
connection to the data source and write updates to it.

A writer is made available through an implementation of the
SyncProvider interface, as discussed in section 1,
"Creating a CachedRowSet Object."
The default reference implementation provider, RIOptimisticProvider,
has its writer implemented to use an optimistic concurrency control
mechanism. That is, it maintains no locks in the underlying database while
the rowset is disconnected from the database and simply checks to see if there
are any conflicts before writing data to the data source.  If there are any
conflicts, it does not write anything to the data source.

The reader/writer facility
provided by the SyncProvider class is pluggable, allowing for the
customization of data retrieval and updating. If a different concurrency
control mechanism is desired, a different implementation of
SyncProvider can be plugged in using the method
setSyncProvider.

In order to use the optimistic concurrency control routine, the
RIOptismisticProvider maintains both its current
value and its original value (the value it had immediately preceding the
current value). Note that if no changes have been made to the data in a
RowSet object, its current values and its original values are the same,
both being the values with which the RowSet object was initially
populated.  However, once any values in the RowSet object have been
changed, the current values and the original values will be different, though at
this stage, the original values are still the initial values. With any subsequent
changes to data in a RowSet object, its original values and current
values will still differ, but its original values will be the values that
were previously the current values.

Keeping track of original values allows the writer to compare the RowSet
object's original value with the value in the database. If the values in
the database differ from the RowSet object's original values, which means that
the values in the database have been changed, there is a conflict.
Whether a writer checks for conflicts, what degree of checking it does, and how
it handles conflicts all depend on how it is implemented.

5.0 Registering and Notifying Listeners
Being JavaBeans components, all rowsets participate in the JavaBeans event
model, inheriting methods for registering listeners and notifying them of
changes from the BaseRowSet class.  A listener for a
CachedRowSet object is a component that wants to be notified
whenever there is a change in the rowset.  For example, if a
CachedRowSet object contains the results of a query and
those
results are being displayed in, say, a table and a bar graph, the table and
bar graph could be registered as listeners with the rowset so that they can
update themselves to reflect changes. To become listeners, the table and
bar graph classes must implement the RowSetListener interface.
Then they can be added to the CachedRowSet object's list of
listeners, as is illustrated in the following lines of code.


   crs.addRowSetListener(table);
   crs.addRowSetListener(barGraph);
Each CachedRowSet method that moves the cursor or changes
data also notifies registered listeners of the changes, so
table and barGraph will be notified when there is
a change in crs.

6.0 Passing Data to Thin Clients
One of the main reasons to use a CachedRowSet object is to
pass data between different components of an application. Because it is
serializable, a CachedRowSet object can be used, for example,
to send the result of a query executed by an enterprise JavaBeans component
running in a server environment over a network to a client running in a
web browser.

While a CachedRowSet object is disconnected, it can be much
leaner than a ResultSet object with the same data.
As a result, it can be especially suitable for sending data to a thin client
such as a PDA, where it would be inappropriate to use a JDBC driver
due to resource limitations or security considerations.
Thus, a CachedRowSet object provides a means to "get rows in"
without the need to implement the full JDBC API.

7.0 Scrolling and Updating
A second major use for CachedRowSet objects is to provide
scrolling and updating for ResultSet objects that
do not provide these capabilities themselves.  In other words, a
CachedRowSet object can be used to augment the
capabilities of a JDBC technology-enabled driver (hereafter called a
"JDBC driver") when the DBMS does not provide full support for scrolling and
updating. To achieve the effect of making a non-scrollble and read-only
ResultSet object scrollable and updatable, a programmer
simply needs to create a CachedRowSet object populated
with that ResultSet object's data.  This is demonstrated
in the following code fragment, where stmt is a
Statement object.


   ResultSet rs = stmt.executeQuery("SELECT * FROM EMPLOYEES");
   CachedRowSetImpl crs = new CachedRowSetImpl();
   crs.populate(rs);

The object crs now contains the data from the table
EMPLOYEES, just as the object rs does.
The difference is that the cursor for crs can be moved
forward, backward, or to a particular row even if the cursor for
rs can move only forward.  In addition, crs is
updatable even if rs is not because by default, a
CachedRowSet object is both scrollable and updatable.

In summary, a CachedRowSet object can be thought of as simply
a disconnected set of rows that are being cached outside of a data source.
Being thin and serializable, it can easily be sent across a wire,
and it is well suited to sending data to a thin client. However, a
CachedRowSet object does have a limitation: It is limited in
size by the amount of data it can store in memory at one time.

8.0 Getting Universal Data Access
Another advantage of the CachedRowSet class is that it makes it
possible to retrieve and store data from sources other than a relational
database. The reader for a rowset can be implemented to read and populate
its rowset with data from any tabular data source, including a spreadsheet
or flat file.
Because both a CachedRowSet object and its metadata can be
created from scratch, a component that acts as a factory for rowsets
can use this capability to create a rowset containing data from
non-SQL data sources. Nevertheless, it is expected that most of the time,
CachedRowSet objects will contain data that was fetched
from an SQL database using the JDBC API.

9.0 Setting Properties
All rowsets maintain a set of properties, which will usually be set using
a tool.  The number and kinds of properties a rowset has will vary,
depending on what the rowset does and how it gets its data.  For example,
rowsets that get their data from a ResultSet object need to
set the properties that are required for making a database connection.
If a rowset uses the DriverManager facility to make a
connection, it needs to set a property for the JDBC URL that identifies
the appropriate driver, and it needs to set the properties that give the
user name and password.
If, on the other hand, the rowset uses a DataSource object
to make the connection, which is the preferred method, it does not need to
set the property for the JDBC URL.  Instead, it needs to set
properties for the logical name of the data source, for the user name,
and for the password.

NOTE:  In order to use a DataSource object for making a
connection, the DataSource object must have been registered
with a naming service that uses the Java Naming and Directory
Interface™ (JNDI) API.  This registration
is usually done by a person acting in the capacity of a system
administrator.

In order to be able to populate itself with data from a database, a rowset
needs to set a command property.  This property is a query that is a
PreparedStatement object, which allows the query to have
parameter placeholders that are set at run time, as opposed to design time.
To set these placeholder parameters with values, a rowset provides
setter methods for setting values of each data type,
similar to the setter methods provided by the PreparedStatement
interface.

The following code fragment illustrates how the CachedRowSet
object crs might have its command property set.  Note that if a
tool is used to set properties, this is the code that the tool would use.


   crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS "
                  "WHERE CREDIT_LIMIT > ? AND REGION = ?");

The values that will be used to set the command's placeholder parameters are
contained in the RowSet object's params field, which is a
Vector object.
The CachedRowSet class provides a set of setter
methods for setting the elements in its params field.  The
following code fragment demonstrates setting the two parameters in the
query from the previous example.


   crs.setInt(1, 5000);
   crs.setString(2, "West");

The params field now contains two elements, each of which is
an array two elements long.  The first element is the parameter number;
the second is the value to be set.
In this case, the first element of params is
1, 5000, and the second element is 2,
"West".  When an application calls the method
execute, it will in turn call on this RowSet object's reader,
which will in turn invoke its readData method. As part of
its implementation, readData will get the values in
params and use them to set the command's placeholder
parameters.
The following code fragment gives an idea of how the reader
does this, after obtaining the Connection object
con.


   PreparedStatement pstmt = con.prepareStatement(crs.getCommand());
   reader.decodeParams();
   // decodeParams figures out which setter methods to use and does something
   // like the following:
   //    for (i = 0; i < params.length; i++) {
   //        pstmt.setObject(i  1, params[i]);
   //    }

At this point, the command for crs is the query "SELECT
FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS WHERE CREDIT_LIMIT > 5000
AND REGION = "West".  After the readData method executes
this command with the following line of code, it will have the data from
rs with which to populate crs.


    ResultSet rs = pstmt.executeQuery();

The preceding code fragments give an idea of what goes on behind the
scenes; they would not appear in an application, which would not invoke
methods like readData and decodeParams.
In contrast, the following code fragment shows what an application might do.
It sets the rowset's command, sets the command's parameters, and executes
the command. Simply by calling the execute method,
crs populates itself with the requested data from the
table CUSTOMERS.


   crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS"
                  "WHERE CREDIT_LIMIT > ? AND REGION = ?");
   crs.setInt(1, 5000);
   crs.setString(2, "West");
   crs.execute();

10.0 Paging Data
Because a CachedRowSet object stores data in memory,
the amount of data that it can contain at any one
time is determined by the amount of memory available. To get around this limitation,
a CachedRowSet object can retrieve data from a ResultSet
object in chunks of data, called pages. To take advantage of this mechanism,
an application sets the number of rows to be included in a page using the method
setPageSize. In other words, if the page size is set to five, a chunk
of five rows of
data will be fetched from the data source at one time. An application can also
optionally set the maximum number of rows that may be fetched at one time.  If the
maximum number of rows is set to zero, or no maximum number of rows is set, there is
no limit to the number of rows that may be fetched at a time.

After properties have been set,
the CachedRowSet object must be populated with data
using either the method populate or the method execute.
The following lines of code demonstrate using the method populate.
Note that this version of the method takes two parameters, a ResultSet
handle and the row in the ResultSet object from which to start
retrieving rows.


    CachedRowSet crs = new CachedRowSetImpl();
    crs.setMaxRows(20);
    crs.setPageSize(4);
    crs.populate(rsHandle, 10);
When this code runs, crs will be populated with four rows from
rsHandle starting with the tenth row.

The next code fragment shows populating a CachedRowSet object using the
method execute, which may or may not take a Connection
object as a parameter.  This code passes execute the Connection
object conHandle.

Note that there are two differences between the following code
fragment and the previous one. First, the method setMaxRows is not
called, so there is no limit set for the number of rows that crs may contain.
(Remember that crs always has the overriding limit of how much data it can
store in memory.) The second difference is that the you cannot pass the method
execute the number of the row in the ResultSet object
from which to start retrieving rows. This method always starts with the first row.


    CachedRowSet crs = new CachedRowSetImpl();
    crs.setPageSize(5);
    crs.execute(conHandle);
After this code has run, crs will contain five rows of data from the
ResultSet object produced by the command for crs. The writer
for crs will use conHandle to connect to the data source and
execute the command for crs. An application is then able to operate on the
data in crs in the same way that it would operate on data in any other
CachedRowSet object.

To access the next page (chunk of data), an application calls the method
nextPage.  This method creates a new CachedRowSet object
and fills it with the next page of data.  For example, assume that the
CachedRowSet object's command returns a ResultSet object
rs with 1000 rows of data.  If the page size has been set to 100, the first
 call to the method nextPage will create a CachedRowSet object
containing the first 100 rows of rs. After doing what it needs to do with the
data in these first 100 rows, the application can again call the method
nextPage to create another CachedRowSet object
with the second 100 rows from rs. The data from the first CachedRowSet
object will no longer be in memory because it is replaced with the data from the
second CachedRowSet object. After the tenth call to the method nextPage,
the tenth CachedRowSet object will contain the last 100 rows of data from
rs, which are stored in memory. At any given time, the data from only one
CachedRowSet object is stored in memory.

The method nextPage returns true as long as the current
page is not the last page of rows and false when there are no more pages.
It can therefore be used in a while loop to retrieve all of the pages,
as is demonstrated in the following lines of code.


    CachedRowSet crs = CachedRowSetImpl();
    crs.setPageSize(100);
    crs.execute(conHandle);

    while(crs.nextPage()) {
        while(crs.next()) {
            . . . // operate on chunks (of 100 rows each) in crs,
                  // row by row
        }
    }
After this code fragment has been run, the application will have traversed all
1000 rows, but it will have had no more than 100 rows in memory at a time.

The CachedRowSet interface also defines the method previousPage.
Just as the method nextPage is analogous to the ResultSet
method next, the method previousPage is analogous to
the ResultSet method previous.  Similar to the method
nextPage, previousPage creates a CachedRowSet
object containing the number of rows set as the page size.  So, for instance, the
method previousPage could be used in a while loop at
the end of the preceding code fragment to navigate back through the pages from the last
page to the first page.
The method previousPage is also similar to nextPage
in that it can be used in a while
loop, except that it returns true as long as there is another page
preceding it and false when there are no more pages ahead of it.

By positioning the cursor after the last row for each page,
as is done in the following code fragment, the method previous
navigates from the last row to the first row in each page.
The code could also have left the cursor before the first row on each page and then
used the method next in a while loop to navigate each page
from the first row to the last row.

The following code fragment assumes a continuation from the previous code fragment,
meaning that the cursor for the tenth CachedRowSet object is on the
last row.  The code moves the cursor to after the last row so that the first
call to the method previous will put the cursor back on the last row.
After going through all of the rows in the last page (the CachedRowSet
object crs), the code then enters
the while loop to get to the ninth page, go through the rows backwards,
go to the eighth page, go through the rows backwards, and so on to the first row
of the first page.



    crs.afterLast();
    while(crs.previous())  {
        . . . // navigate through the rows, last to first
    {
    while(crs.previousPage())  {
        crs.afterLast();
        while(crs.previous())  {
            . . . // go from the last row to the first row of each page
        }
    }
raw docstring

javax.sql.rowset.core

No vars found in this namespace.

javax.sql.rowset.FilteredRowSet

The standard interface that all standard implementations of FilteredRowSet must implement. The FilteredRowSetImpl class provides the reference implementation which may be extended if required. Alternatively, a vendor is free to implement its own version by implementing this interface.

1.0 Background

There are occasions when a RowSet object has a need to provide a degree of filtering to its contents. One possible solution is to provide a query language for all standard RowSet implementations; however, this is an impractical approach for lightweight components such as disconnected RowSet objects. The FilteredRowSet interface seeks to address this need without supplying a heavyweight query language along with the processing that such a query language would require.

A JDBC FilteredRowSet standard implementation implements the RowSet interfaces and extends the CachedRowSet™ class. The CachedRowSet class provides a set of protected cursor manipulation methods, which a FilteredRowSet implementation can override to supply filtering support.

2.0 Predicate Sharing

If a FilteredRowSet implementation is shared using the inherited createShared method in parent interfaces, the Predicate should be shared without modification by all FilteredRowSet instance clones.

3.0 Usage

By implementing a Predicate (see example in Predicate class JavaDoc), a FilteredRowSet could then be used as described below.

FilteredRowSet frs = new FilteredRowSetImpl();
frs.populate(rs);

Range name = new Range("Alpha", "Bravo", "columnName");
frs.setFilter(name);

frs.next() // only names from "Alpha" to "Bravo" will be returned

In the example above, we initialize a Range object which implements the Predicate interface. This object expresses the following constraints: All rows outputted or modified from this FilteredRowSet object must fall between the values 'Alpha' and 'Bravo' both values inclusive, in the column 'columnName'. If a filter is applied to a FilteredRowSet object that contains no data that falls within the range of the filter, no rows are returned.

This framework allows multiple classes implementing predicates to be used in combination to achieved the required filtering result with out the need for query language processing.

4.0 Updating a FilteredRowSet Object The predicate set on a FilteredRowSet object applies a criterion on all rows in a RowSet object to manage a subset of rows in a RowSet object. This criterion governs the subset of rows that are visible and also defines which rows can be modified, deleted or inserted.

Therefore, the predicate set on a FilteredRowSet object must be considered as bi-directional and the set criterion as the gating mechanism for all views and updates to the FilteredRowSet object. Any attempt to update the FilteredRowSet that violates the criterion will result in a SQLException object being thrown.

The FilteredRowSet range criterion can be modified by applying a new Predicate object to the FilteredRowSet instance at any time. This is possible if no additional references to the FilteredRowSet object are detected. A new filter has has an immediate effect on criterion enforcement within the FilteredRowSet object, and all subsequent views and updates will be subject to similar enforcement.

5.0 Behavior of Rows Outside the Filter Rows that fall outside of the filter set on a FilteredRowSet object cannot be modified until the filter is removed or a new filter is applied.

Furthermore, only rows that fall within the bounds of a filter will be synchronized with the data source.

The standard interface that all standard implementations of
FilteredRowSet must implement. The FilteredRowSetImpl class
provides the reference implementation which may be extended if required.
Alternatively, a vendor is free to implement its own version
by implementing this interface.

1.0 Background

There are occasions when a RowSet object has a need to provide a degree
of filtering to its contents. One possible solution is to provide
a query language for all standard RowSet implementations; however,
this is an impractical approach for lightweight components such as disconnected
RowSet
objects. The FilteredRowSet interface seeks to address this need
without supplying a heavyweight query language along with the processing that
such a query language would require.

A JDBC FilteredRowSet standard implementation implements the
RowSet interfaces and extends the
CachedRowSet™ class. The
CachedRowSet class provides a set of protected cursor manipulation
methods, which a FilteredRowSet implementation can override
to supply filtering support.

2.0 Predicate Sharing

If a FilteredRowSet implementation is shared using the
inherited createShared method in parent interfaces, the
Predicate should be shared without modification by all
FilteredRowSet instance clones.

3.0 Usage

By implementing a Predicate (see example in Predicate
class JavaDoc), a FilteredRowSet could then be used as described
below.



    FilteredRowSet frs = new FilteredRowSetImpl();
    frs.populate(rs);

    Range name = new Range("Alpha", "Bravo", "columnName");
    frs.setFilter(name);

    frs.next() // only names from "Alpha" to "Bravo" will be returned
In the example above, we initialize a Range object which
implements the Predicate interface. This object expresses
the following constraints: All rows outputted or modified from this
FilteredRowSet object must fall between the values 'Alpha' and
'Bravo' both values inclusive, in the column 'columnName'. If a filter is
applied to a FilteredRowSet object that contains no data that
falls within the range of the filter, no rows are returned.

This framework allows multiple classes implementing predicates to be
used in combination to achieved the required filtering result with
out the need for query language processing.

4.0 Updating a FilteredRowSet Object
The predicate set on a FilteredRowSet object
applies a criterion on all rows in a
RowSet object to manage a subset of rows in a RowSet
object. This criterion governs the subset of rows that are visible and also
defines which rows can be modified, deleted or inserted.

Therefore, the predicate set on a FilteredRowSet object must be
considered as bi-directional and the set criterion as the gating mechanism
for all views and updates to the FilteredRowSet object. Any attempt
to update the FilteredRowSet that violates the criterion will
result in a SQLException object being thrown.

The FilteredRowSet range criterion can be modified by applying
a new Predicate object to the FilteredRowSet
instance at any time. This is  possible if no additional references to the
FilteredRowSet object are detected. A new filter has has an
immediate effect on criterion enforcement within the
FilteredRowSet object, and all subsequent views and updates will be
subject to similar enforcement.

5.0 Behavior of Rows Outside the Filter
Rows that fall outside of the filter set on a FilteredRowSet
object cannot be modified until the filter is removed or a
new filter is applied.

Furthermore, only rows that fall within the bounds of a filter will be
synchronized with the data source.
raw docstring

javax.sql.rowset.JdbcRowSet

The standard interface that all standard implementations of JdbcRowSet must implement.

1.0 Overview A wrapper around a ResultSet object that makes it possible to use the result set as a JavaBeans™ component. Thus, a JdbcRowSet object can be one of the Beans that a tool makes available for composing an application. Because a JdbcRowSet is a connected rowset, that is, it continually maintains its connection to a database using a JDBC technology-enabled driver, it also effectively makes the driver a JavaBeans component.

Because it is always connected to its database, an instance of JdbcRowSet can simply take calls invoked on it and in turn call them on its ResultSet object. As a consequence, a result set can, for example, be a component in a Swing application.

Another advantage of a JdbcRowSet object is that it can be used to make a ResultSet object scrollable and updatable. All RowSet objects are by default scrollable and updatable. If the driver and database being used do not support scrolling and/or updating of result sets, an application can populate a JdbcRowSet object with the data of a ResultSet object and then operate on the JdbcRowSet object as if it were the ResultSet object.

2.0 Creating a JdbcRowSet Object The reference implementation of the JdbcRowSet interface, JdbcRowSetImpl, provides an implementation of the default constructor. A new instance is initialized with default values, which can be set with new values as needed. A new instance is not really functional until its execute method is called. In general, this method does the following:

establishes a connection with a database creates a PreparedStatement object and sets any of its placeholder parameters executes the statement to create a ResultSet object

If the execute method is successful, it will set the appropriate private JdbcRowSet fields with the following:

a Connection object -- the connection between the rowset and the database a PreparedStatement object -- the query that produces the result set a ResultSet object -- the result set that the rowset's command produced and that is being made, in effect, a JavaBeans component

If these fields have not been set, meaning that the execute method has not executed successfully, no methods other than execute and close may be called on the rowset. All other public methods will throw an exception.

Before calling the execute method, however, the command and properties needed for establishing a connection must be set. The following code fragment creates a JdbcRowSetImpl object, sets the command and connection properties, sets the placeholder parameter, and then invokes the method execute.

JdbcRowSetImpl jrs = new JdbcRowSetImpl();
jrs.setCommand("SELECT * FROM TITLES WHERE TYPE = ?");
jrs.setURL("jdbc:myDriver:myAttribute");
jrs.setUsername("cervantes");
jrs.setPassword("sancho");
jrs.setString(1, "BIOGRAPHY");
jrs.execute();

The variable jrs now represents an instance of JdbcRowSetImpl that is a thin wrapper around the ResultSet object containing all the rows in the table TITLES where the type of book is biography. At this point, operations called on jrs will affect the rows in the result set, which is effectively a JavaBeans component.

The implementation of the RowSet method execute in the JdbcRowSet reference implementation differs from that in the CachedRowSet™ reference implementation to account for the different requirements of connected and disconnected RowSet objects.

The standard interface that all standard implementations of
JdbcRowSet must implement.

1.0 Overview
A wrapper around a ResultSet object that makes it possible
to use the result set as a JavaBeans™
component.  Thus, a JdbcRowSet object can be one of the Beans that
a tool makes available for composing an application.  Because
a JdbcRowSet is a connected rowset, that is, it continually
maintains its connection to a database using a JDBC technology-enabled
driver, it also effectively makes the driver a JavaBeans component.

Because it is always connected to its database, an instance of
JdbcRowSet
can simply take calls invoked on it and in turn call them on its
ResultSet object. As a consequence, a result set can, for
example, be a component in a Swing application.

Another advantage of a JdbcRowSet object is that it can be
used to make a ResultSet object scrollable and updatable.  All
RowSet objects are by default scrollable and updatable. If
the driver and database being used do not support scrolling and/or updating
of result sets, an application can populate a JdbcRowSet object
with the data of a ResultSet object and then operate on the
JdbcRowSet object as if it were the ResultSet
object.

2.0 Creating a JdbcRowSet Object
The reference implementation of the JdbcRowSet interface,
JdbcRowSetImpl, provides an implementation of
the default constructor.  A new instance is initialized with
default values, which can be set with new values as needed. A
new instance is not really functional until its execute
method is called. In general, this method does the following:

   establishes a connection with a database
   creates a PreparedStatement object and sets any of its
       placeholder parameters
   executes the statement to create a ResultSet object

If the execute method is successful, it will set the
appropriate private JdbcRowSet fields with the following:

  a Connection object -- the connection between the rowset
      and the database
  a PreparedStatement object -- the query that produces
      the result set
  a ResultSet object -- the result set that the rowset's
      command produced and that is being made, in effect, a JavaBeans
      component

If these fields have not been set, meaning that the execute
method has not executed successfully, no methods other than
execute and close may be called on the
rowset.  All other public methods will throw an exception.

Before calling the execute method, however, the command
and properties needed for establishing a connection must be set.
The following code fragment creates a JdbcRowSetImpl object,
sets the command and connection properties, sets the placeholder parameter,
and then invokes the method execute.


    JdbcRowSetImpl jrs = new JdbcRowSetImpl();
    jrs.setCommand("SELECT * FROM TITLES WHERE TYPE = ?");
    jrs.setURL("jdbc:myDriver:myAttribute");
    jrs.setUsername("cervantes");
    jrs.setPassword("sancho");
    jrs.setString(1, "BIOGRAPHY");
    jrs.execute();
The variable jrs now represents an instance of
JdbcRowSetImpl that is a thin wrapper around the
ResultSet object containing all the rows in the
table TITLES where the type of book is biography.
At this point, operations called on jrs will
affect the rows in the result set, which is effectively a JavaBeans
component.

The implementation of the RowSet method execute in the
JdbcRowSet reference implementation differs from that in the
CachedRowSet™
reference implementation to account for the different
requirements of connected and disconnected RowSet objects.
raw docstring

javax.sql.rowset.Joinable

1.0 Background The Joinable interface provides the methods for getting and setting a match column, which is the basis for forming the SQL JOIN formed by adding RowSet objects to a JoinRowSet object.

Any standard RowSet implementation may implement the Joinable interface in order to be added to a JoinRowSet object. Implementing this interface gives a RowSet object the ability to use Joinable methods, which set, retrieve, and get information about match columns. An application may add a RowSet object that has not implemented the Joinable interface to a JoinRowSet object, but to do so it must use one of the JoinRowSet.addRowSet methods that takes both a RowSet object and a match column or an array of RowSet objects and an array of match columns.

To get access to the methods in the Joinable interface, a RowSet object implements at least one of the five standard RowSet interfaces and also implements the Joinable interface. In addition, most RowSet objects extend the BaseRowSet class. For example:

class MyRowSetImpl extends BaseRowSet implements CachedRowSet, Joinable {
    :
    :
}

2.0 Usage Guidelines

The methods in the Joinable interface allow a RowSet object to set a match column, retrieve a match column, or unset a match column, which is the column upon which an SQL JOIN can be based. An instance of a class that implements these methods can be added to a JoinRowSet object to allow an SQL JOIN relationship to be established.

CachedRowSet crs = new MyRowSetImpl();
crs.populate((ResultSet)rs);
(Joinable)crs.setMatchColumnIndex(1);

JoinRowSet jrs = new JoinRowSetImpl();
jrs.addRowSet(crs);

In the previous example, crs is a CachedRowSet object that has implemented the Joinable interface. In the following example, crs2 has not, so it must supply the match column as an argument to the addRowSet method. This example assumes that column 1 is the match column.

CachedRowSet crs2 = new MyRowSetImpl();
crs2.populate((ResultSet)rs);

JoinRowSet jrs2 = new JoinRowSetImpl();
jrs2.addRowSet(crs2, 1);

The JoinRowSet interface makes it possible to get data from one or more RowSet objects consolidated into one table without having to incur the expense of creating a connection to a database. It is therefore ideally suited for use by disconnected RowSet objects. Nevertheless, any RowSet object may implement this interface regardless of whether it is connected or disconnected. Note that a JdbcRowSet object, being always connected to its data source, can become part of an SQL JOIN directly without having to become part of a JoinRowSet object.

3.0 Managing Multiple Match Columns The index array passed into the setMatchColumn methods indicates how many match columns are being set (the length of the array) in addition to which columns will be used for the match. For example:

int[] i = {1, 2, 4, 7}; // indicates four match columns, with column
                        // indexes 1, 2, 4, 7 participating in the JOIN.
Joinable.setMatchColumn(i);

Subsequent match columns may be added as follows to a different Joinable object (a RowSet object that has implemented the Joinable interface).

int[] w = {3, 2, 5, 3};
Joinable2.setMatchColumn(w);

When an application adds two or more RowSet objects to a JoinRowSet object, the order of the indexes in the array is particularly important. Each index of the array maps directly to the corresponding index of the previously added RowSet object. If overlap or underlap occurs, the match column data is maintained in the event an additional Joinable RowSet is added and needs to relate to the match column data. Therefore, applications can set multiple match columns in any order, but this order has a direct effect on the outcome of the SQL JOIN.

This assertion applies in exactly the same manner when column names are used rather than column indexes to indicate match columns.

1.0 Background
The Joinable interface provides the methods for getting and
setting a match column, which is the basis for forming the SQL JOIN
formed by adding RowSet objects to a JoinRowSet
object.

Any standard RowSet implementation may implement
the Joinable interface in order to be
added to a JoinRowSet object. Implementing this interface gives
a RowSet object the ability to use Joinable methods,
which set, retrieve, and get information about match columns.  An
application may add a
RowSet object that has not implemented the Joinable
interface to a JoinRowSet object, but to do so it must use one
of the JoinRowSet.addRowSet methods that takes both a
RowSet object and a match column or an array of RowSet
objects and an array of match columns.

To get access to the methods in the Joinable interface, a
RowSet object implements at least one of the
five standard RowSet interfaces and also implements the
Joinable interface.  In addition, most RowSet
objects extend the BaseRowSet class.  For example:


    class MyRowSetImpl extends BaseRowSet implements CachedRowSet, Joinable {
        :
        :
    }

2.0 Usage Guidelines

The methods in the Joinable interface allow a RowSet object
to set a match column, retrieve a match column, or unset a match column, which is
the column upon which an SQL JOIN can be based.
An instance of a class that implements these methods can be added to a
JoinRowSet object to allow an SQL JOIN relationship to
 be established.



    CachedRowSet crs = new MyRowSetImpl();
    crs.populate((ResultSet)rs);
    (Joinable)crs.setMatchColumnIndex(1);

    JoinRowSet jrs = new JoinRowSetImpl();
    jrs.addRowSet(crs);
In the previous example, crs is a CachedRowSet object that
has implemented the Joinable interface.  In the following example,
crs2 has not, so it must supply the match column as an argument to the
addRowSet method. This example assumes that column 1 is the match
column.


    CachedRowSet crs2 = new MyRowSetImpl();
    crs2.populate((ResultSet)rs);

    JoinRowSet jrs2 = new JoinRowSetImpl();
    jrs2.addRowSet(crs2, 1);

The JoinRowSet interface makes it possible to get data from one or
more RowSet objects consolidated into one table without having to incur
the expense of creating a connection to a database. It is therefore ideally suited
for use by disconnected RowSet objects. Nevertheless, any
RowSet object may implement this interface
regardless of whether it is connected or disconnected. Note that a
JdbcRowSet object, being always connected to its data source, can
become part of an SQL JOIN directly without having to become part
of a JoinRowSet object.

3.0 Managing Multiple Match Columns
The index array passed into the setMatchColumn methods indicates
how many match columns are being set (the length of the array) in addition to
which columns will be used for the match. For example:


    int[] i = {1, 2, 4, 7}; // indicates four match columns, with column
                            // indexes 1, 2, 4, 7 participating in the JOIN.
    Joinable.setMatchColumn(i);
Subsequent match columns may be added as follows to a different Joinable
object (a RowSet object that has implemented the Joinable
interface).


    int[] w = {3, 2, 5, 3};
    Joinable2.setMatchColumn(w);
When an application adds two or more RowSet objects to a
JoinRowSet object, the order of the indexes in the array is
particularly important. Each index of
the array maps directly to the corresponding index of the previously added
RowSet object. If overlap or underlap occurs, the match column
data is maintained in the event an additional Joinable RowSet is
added and needs to relate to the match column data. Therefore, applications
can set multiple match columns in any order, but
this order has a direct effect on the outcome of the SQL JOIN.

This assertion applies in exactly the same manner when column names are used
rather than column indexes to indicate match columns.
raw docstring

javax.sql.rowset.JoinRowSet

The JoinRowSet interface provides a mechanism for combining related data from different RowSet objects into one JoinRowSet object, which represents an SQL JOIN. In other words, a JoinRowSet object acts as a container for the data from RowSet objects that form an SQL JOIN relationship.

The Joinable interface provides the methods for setting, retrieving, and unsetting a match column, the basis for establishing an SQL JOIN relationship. The match column may alternatively be set by supplying it to the appropriate version of the JointRowSet method addRowSet.

1.0 Overview Disconnected RowSet objects (CachedRowSet objects and implementations extending the CachedRowSet interface) do not have a standard way to establish an SQL JOIN between RowSet objects without the expensive operation of reconnecting to the data source. The JoinRowSet interface is specifically designed to address this need.

Any RowSet object can be added to a JoinRowSet object to become part of an SQL JOIN relationship. This means that both connected and disconnected RowSet objects can be part of a JOIN. RowSet objects operating in a connected environment (JdbcRowSet objects) are encouraged to use the database to which they are already connected to establish SQL JOIN relationships between tables directly. However, it is possible for a JdbcRowSet object to be added to a JoinRowSet object if necessary.

Any number of RowSet objects can be added to an instance of JoinRowSet provided that they can be related in an SQL JOIN. By definition, the SQL JOIN statement is used to combine the data contained in two or more relational database tables based upon a common attribute. The Joinable interface provides the methods for establishing a common attribute, which is done by setting a match column. The match column commonly coincides with the primary key, but there is no requirement that the match column be the same as the primary key. By establishing and then enforcing column matches, a JoinRowSet object establishes JOIN relationships between RowSet objects without the assistance of an available relational database.

The type of JOIN to be established is determined by setting one of the JoinRowSet constants using the method setJoinType. The following SQL JOIN types can be set:

CROSS_JOIN FULL_JOIN INNER_JOIN - the default if no JOIN type has been set LEFT_OUTER_JOIN RIGHT_OUTER_JOIN

Note that if no type is set, the JOIN will automatically be an inner join. The comments for the fields in the JoinRowSet interface explain these JOIN types, which are standard SQL JOIN types.

2.0 Using a JoinRowSet Object for Creating a JOIN When a JoinRowSet object is created, it is empty. The first RowSet object to be added becomes the basis for the JOIN relationship. Applications must determine which column in each of the RowSet objects to be added to the JoinRowSet object should be the match column. All of the RowSet objects must contain a match column, and the values in each match column must be ones that can be compared to values in the other match columns. The columns do not have to have the same name, though they often do, and they do not have to store the exact same data type as long as the data types can be compared.

A match column can be be set in two ways:

By calling the Joinable method setMatchColumn This is the only method that can set the match column before a RowSet object is added to a JoinRowSet object. The RowSet object must have implemented the Joinable interface in order to use the method setMatchColumn. Once the match column value has been set, this method can be used to reset the match column at any time. By calling one of the versions of the JoinRowSet method addRowSet that takes a column name or number (or an array of column names or numbers) Four of the five addRowSet methods take a match column as a parameter. These four methods set or reset the match column at the time a RowSet object is being added to a JoinRowSet object.

3.0 Sample Usage

The following code fragment adds two CachedRowSet objects to a JoinRowSet object. Note that in this example, no SQL JOIN type is set, so the default JOIN type, which is INNER_JOIN, is established.

In the following code fragment, the table EMPLOYEES, whose match column is set to the first column (EMP_ID), is added to the JoinRowSet object jrs. Then the table ESSP_BONUS_PLAN, whose match column is likewise the EMP_ID column, is added. When this second table is added to jrs, only the rows in ESSP_BONUS_PLAN whose EMP_ID value matches an EMP_ID value in the EMPLOYEES table are added. In this case, everyone in the bonus plan is an employee, so all of the rows in the table ESSP_BONUS_PLAN are added to the JoinRowSet object. In this example, both CachedRowSet objects being added have implemented the Joinable interface and can therefore call the Joinable method setMatchColumn.

JoinRowSet jrs = new JoinRowSetImpl();

ResultSet rs1 = stmt.executeQuery("SELECT * FROM EMPLOYEES");
CachedRowSet empl = new CachedRowSetImpl();
empl.populate(rs1);
empl.setMatchColumn(1);
jrs.addRowSet(empl);

ResultSet rs2 = stmt.executeQuery("SELECT * FROM ESSP_BONUS_PLAN");
CachedRowSet bonus = new CachedRowSetImpl();
bonus.populate(rs2);
bonus.setMatchColumn(1); // EMP_ID is the first column
jrs.addRowSet(bonus);

At this point, jrs is an inside JOIN of the two RowSet objects based on their EMP_ID columns. The application can now browse the combined data as if it were browsing one single RowSet object. Because jrs is itself a RowSet object, an application can navigate or modify it using RowSet methods.

jrs.first();
int employeeID = jrs.getInt(1);
String employeeName = jrs.getString(2);

Note that because the SQL JOIN must be enforced when an application adds a second or subsequent RowSet object, there may be an initial degradation in performance while the JOIN is being performed.

The following code fragment adds an additional CachedRowSet object. In this case, the match column (EMP_ID) is set when the CachedRowSet object is added to the JoinRowSet object.

ResultSet rs3 = stmt.executeQuery("SELECT * FROM 401K_CONTRIB");
CachedRowSet fourO1k = new CachedRowSetImpl();
four01k.populate(rs3);
jrs.addRowSet(four01k, 1);

The JoinRowSet object jrs now contains values from all three tables. The data in each row in four01k in which the value for the EMP_ID column matches a value for the EMP_ID column in jrs has been added to jrs.

4.0 JoinRowSet Methods The JoinRowSet interface supplies several methods for adding RowSet objects and for getting information about the JoinRowSet object.

Methods for adding one or more RowSet objects These methods allow an application to add one RowSet object at a time or to add multiple RowSet objects at one time. In either case, the methods may specify the match column for each RowSet object being added. Methods for getting information One method retrieves the RowSet objects in the JoinRowSet object, and another method retrieves the RowSet names. A third method retrieves either the SQL WHERE clause used behind the scenes to form the JOIN or a text description of what the WHERE clause does. Methods related to the type of JOIN One method sets the JOIN type, and five methods find out whether the JoinRowSet object supports a given type. A method to make a separate copy of the JoinRowSet object This method creates a copy that can be persisted to the data source.

The JoinRowSet interface provides a mechanism for combining related
data from different RowSet objects into one JoinRowSet
object, which represents an SQL JOIN.
In other words, a JoinRowSet object acts as a
container for the data from RowSet objects that form an SQL
JOIN relationship.

The Joinable interface provides the methods for setting,
retrieving, and unsetting a match column, the basis for
establishing an SQL JOIN relationship. The match column may
alternatively be set by supplying it to the appropriate version of the
JointRowSet method addRowSet.

1.0 Overview
Disconnected RowSet objects (CachedRowSet objects
and implementations extending the CachedRowSet interface)
do not have a standard way to establish an SQL JOIN between
RowSet objects without the expensive operation of
reconnecting to the data source. The JoinRowSet
interface is specifically designed to address this need.

Any RowSet object
can be added to a JoinRowSet object to become
part of an SQL JOIN relationship. This means that both connected
and disconnected RowSet objects can be part of a JOIN.
RowSet objects operating in a connected environment
(JdbcRowSet objects) are
encouraged to use the database to which they are already
connected to establish SQL JOIN relationships between
tables directly. However, it is possible for a
JdbcRowSet object to be added to a JoinRowSet object
if necessary.

Any number of RowSet objects can be added to an
instance of JoinRowSet provided that they
can be related in an SQL JOIN.
By definition, the SQL JOIN statement is used to
combine the data contained in two or more relational database tables based
upon a common attribute. The Joinable interface provides the methods
for establishing a common attribute, which is done by setting a
match column. The match column commonly coincides with
the primary key, but there is
no requirement that the match column be the same as the primary key.
By establishing and then enforcing column matches,
a JoinRowSet object establishes JOIN relationships
between RowSet objects without the assistance of an available
relational database.

The type of JOIN to be established is determined by setting
one of the JoinRowSet constants using the method
setJoinType. The following SQL JOIN types can be set:

 CROSS_JOIN
 FULL_JOIN
 INNER_JOIN - the default if no JOIN type has been set
 LEFT_OUTER_JOIN
 RIGHT_OUTER_JOIN

Note that if no type is set, the JOIN will automatically be an
inner join. The comments for the fields in the
JoinRowSet interface explain these JOIN types, which are
standard SQL JOIN types.

2.0 Using a JoinRowSet Object for Creating a JOIN
When a JoinRowSet object is created, it is empty.
The first RowSet object to be added becomes the basis for the
JOIN relationship.
Applications must determine which column in each of the
RowSet objects to be added to the JoinRowSet object
should be the match column. All of the
RowSet objects must contain a match column, and the values in
each match column must be ones that can be compared to values in the other match
columns. The columns do not have to have the same name, though they often do,
and they do not have to store the exact same data type as long as the data types
can be compared.

A match column can be be set in two ways:

 By calling the Joinable method setMatchColumn
 This is the only method that can set the match column before a RowSet
 object is added to a JoinRowSet object. The RowSet object
 must have implemented the Joinable interface in order to use the method
 setMatchColumn. Once the match column value
 has been set, this method can be used to reset the match column at any time.
 By calling one of the versions of the JoinRowSet method
 addRowSet that takes a column name or number (or an array of
 column names or numbers)
 Four of the five addRowSet methods take a match column as a parameter.
 These four methods set or reset the match column at the time a RowSet
 object is being added to a JoinRowSet object.

3.0 Sample Usage

The following code fragment adds two CachedRowSet
objects to a JoinRowSet object. Note that in this example,
no SQL JOIN type is set, so the default JOIN type,
which is INNER_JOIN, is established.

In the following code fragment, the table EMPLOYEES, whose match
column is set to the first column (EMP_ID), is added to the
JoinRowSet object jrs. Then
the table ESSP_BONUS_PLAN, whose match column is likewise
the EMP_ID column, is added. When this second
table is added to jrs, only the rows in
ESSP_BONUS_PLAN whose EMP_ID value matches an
EMP_ID value in the EMPLOYEES table are added.
In this case, everyone in the bonus plan is an employee, so all of the rows
in the table ESSP_BONUS_PLAN are added to the JoinRowSet
object.  In this example, both CachedRowSet objects being added
have implemented the Joinable interface and can therefore call
the Joinable method setMatchColumn.


    JoinRowSet jrs = new JoinRowSetImpl();

    ResultSet rs1 = stmt.executeQuery("SELECT * FROM EMPLOYEES");
    CachedRowSet empl = new CachedRowSetImpl();
    empl.populate(rs1);
    empl.setMatchColumn(1);
    jrs.addRowSet(empl);

    ResultSet rs2 = stmt.executeQuery("SELECT * FROM ESSP_BONUS_PLAN");
    CachedRowSet bonus = new CachedRowSetImpl();
    bonus.populate(rs2);
    bonus.setMatchColumn(1); // EMP_ID is the first column
    jrs.addRowSet(bonus);

At this point, jrs is an inside JOIN of the two RowSet objects
based on their EMP_ID columns. The application can now browse the
combined data as if it were browsing one single RowSet object.
Because jrs is itself a RowSet object, an application can
navigate or modify it using RowSet methods.


    jrs.first();
    int employeeID = jrs.getInt(1);
    String employeeName = jrs.getString(2);

Note that because the SQL JOIN must be enforced when an application
adds a second or subsequent RowSet object, there
may be an initial degradation in performance while the JOIN is
being performed.

The following code fragment adds an additional CachedRowSet object.
In this case, the match column (EMP_ID) is set when the
CachedRowSet object is added to the JoinRowSet object.


    ResultSet rs3 = stmt.executeQuery("SELECT * FROM 401K_CONTRIB");
    CachedRowSet fourO1k = new CachedRowSetImpl();
    four01k.populate(rs3);
    jrs.addRowSet(four01k, 1);

The JoinRowSet object jrs now contains values from all three
tables. The data in each row in four01k in which the value for the
EMP_ID column matches a value for the EMP_ID column
in jrs has been added to jrs.

4.0 JoinRowSet Methods
The JoinRowSet interface supplies several methods for adding
RowSet objects and for getting information about the
JoinRowSet object.

  Methods for adding one or more RowSet objects
      These methods allow an application to add one RowSet object
      at a time or to add multiple RowSet objects at one time. In
      either case, the methods may specify the match column for each
      RowSet object being added.
  Methods for getting information
      One method retrieves the RowSet objects in the
      JoinRowSet object, and another method retrieves the
      RowSet names.  A third method retrieves either the SQL
      WHERE clause used behind the scenes to form the
      JOIN or a text description of what the WHERE
      clause does.
  Methods related to the type of JOIN
      One method sets the JOIN type, and five methods find out whether
      the JoinRowSet object supports a given type.
  A method to make a separate copy of the JoinRowSet object
      This method creates a copy that can be persisted to the data source.
raw docstring

javax.sql.rowset.Predicate

The standard interface that provides the framework for all FilteredRowSet objects to describe their filters.

1.0 Background The Predicate interface is a standard interface that applications can implement to define the filter they wish to apply to a a FilteredRowSet object. A FilteredRowSet object consumes implementations of this interface and enforces the constraints defined in the implementation of the method evaluate. A FilteredRowSet object enforces the filter constraints in a bi-directional manner: It outputs only rows that are within the constraints of the filter; and conversely, it inserts, modifies, or updates only rows that are within the constraints of the filter.

2.0 Implementation Guidelines In order to supply a predicate for the FilteredRowSet. this interface must be implemented. At this time, the JDBC RowSet Implementations (JSR-114) does not specify any standard filters definitions. By specifying a standard means and mechanism for a range of filters to be defined and deployed with both the reference and vendor implementations of the FilteredRowSet interface, this allows for a flexible and application motivated implementations of Predicate to emerge.

A sample implementation would look something like this:

public class Range implements Predicate {

  private int[] lo;
  private int[] hi;
  private int[] idx;

  public Range(int[] lo, int[] hi, int[] idx) {
     this.lo = lo;
     this.hi = hi;
     this.idx = idx;
  }

 public boolean evaluate(RowSet rs) {

     // Check the present row determine if it lies
     // within the filtering criteria.

     for (int i = 0; i < idx.length; i++) {
        int value;
        try {
            value = (Integer) rs.getObject(idx[i]);
        } catch (SQLException ex) {
            Logger.getLogger(Range.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }

        if (value < lo[i] && value > hi[i]) {
            // outside of filter constraints
            return false;
        }
    }
    // Within filter constraints
   return true;
 }

}

The example above implements a simple range predicate. Note, that implementations should but are not required to provide String and integer index based constructors to provide for JDBC RowSet Implementation applications that use both column identification conventions.

The standard interface that provides the framework for all
FilteredRowSet objects to describe their filters.

1.0 Background
The Predicate interface is a standard interface that
applications can implement to define the filter they wish to apply to a
a FilteredRowSet object. A FilteredRowSet
object consumes implementations of this interface and enforces the
constraints defined in the implementation of the method evaluate.
A FilteredRowSet object enforces the filter constraints in a
bi-directional manner: It outputs only rows that are within
the constraints of the filter; and conversely, it inserts, modifies, or updates
only rows that are within the constraints of the filter.

2.0 Implementation Guidelines
In order to supply a predicate for the FilteredRowSet.
this interface must be implemented.  At this time, the JDBC RowSet
Implementations (JSR-114) does not specify any standard filters definitions.
By specifying a standard means and mechanism for a range of filters to be
defined and deployed with both the reference and vendor implementations
of the FilteredRowSet interface, this allows for a flexible
and application motivated implementations of Predicate to emerge.

A sample implementation would look something like this:


   public class Range implements Predicate {

      private int[] lo;
      private int[] hi;
      private int[] idx;

      public Range(int[] lo, int[] hi, int[] idx) {
         this.lo = lo;
         this.hi = hi;
         this.idx = idx;
      }

     public boolean evaluate(RowSet rs) {

         // Check the present row determine if it lies
         // within the filtering criteria.

         for (int i = 0; i < idx.length; i++) {
            int value;
            try {
                value = (Integer) rs.getObject(idx[i]);
            } catch (SQLException ex) {
                Logger.getLogger(Range.class.getName()).log(Level.SEVERE, null, ex);
                return false;
            }

            if (value < lo[i] && value > hi[i]) {
                // outside of filter constraints
                return false;
            }
        }
        // Within filter constraints
       return true;
     }
  }

The example above implements a simple range predicate. Note, that
implementations should but are not required to provide String
and integer index based constructors to provide for JDBC RowSet Implementation
applications that use both column identification conventions.
raw docstring

javax.sql.rowset.RowSetFactory

An interface that defines the implementation of a factory that is used to obtain different types of RowSet implementations.

An interface that defines the implementation of a factory that is used
to obtain different types of RowSet implementations.
raw docstring

javax.sql.rowset.RowSetMetaDataImpl

Provides implementations for the methods that set and get metadata information about a RowSet object's columns. A RowSetMetaDataImpl object keeps track of the number of columns in the rowset and maintains an internal array of column attributes for each column.

A RowSet object creates a RowSetMetaDataImpl object internally in order to set and retrieve information about its columns.

NOTE: All metadata in a RowSetMetaDataImpl object should be considered as unavailable until the RowSet object that it describes is populated. Therefore, any RowSetMetaDataImpl method that retrieves information is defined as having unspecified behavior when it is called before the RowSet object contains data.

Provides implementations for the methods that set and get
metadata information about a RowSet object's columns.
A RowSetMetaDataImpl object keeps track of the
number of columns in the rowset and maintains an internal array
of column attributes for each column.

A RowSet object creates a RowSetMetaDataImpl
object internally in order to set and retrieve information about
its columns.

NOTE: All metadata in a RowSetMetaDataImpl object
should be considered as unavailable until the RowSet object
that it describes is populated.
Therefore, any RowSetMetaDataImpl method that retrieves information
is defined as having unspecified behavior when it is called
before the RowSet object contains data.
raw docstring

javax.sql.rowset.RowSetProvider

A factory API that enables applications to obtain a RowSetFactory implementation that can be used to create different types of RowSet implementations.

Example:

RowSetFactory aFactory = RowSetProvider.newFactory(); CachedRowSet crs = aFactory.createCachedRowSet(); ... RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null); WebRowSet wrs = rsf.createWebRowSet();

Tracing of this class may be enabled by setting the System property javax.sql.rowset.RowSetFactory.debug to any value but false.

A factory API that enables applications to obtain a
RowSetFactory implementation  that can be used to create different
types of RowSet implementations.

Example:



RowSetFactory aFactory = RowSetProvider.newFactory();
CachedRowSet crs = aFactory.createCachedRowSet();
...
RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);
WebRowSet wrs = rsf.createWebRowSet();

Tracing of this class may be enabled by setting the System property
javax.sql.rowset.RowSetFactory.debug to any value but false.
raw docstring

javax.sql.rowset.RowSetWarning

An extension of SQLException that provides information about database warnings set on RowSet objects. Warnings are silently chained to the object whose method call caused it to be reported. This class complements the SQLWarning class.

Rowset warnings may be retrieved from JdbcRowSet, CachedRowSet™, WebRowSet, FilteredRowSet, or JoinRowSet implementations. To retrieve the first warning reported on any RowSet implementation, use the method getRowSetWarnings defined in the JdbcRowSet interface or the CachedRowSet interface. To retrieve a warning chained to the first warning, use the RowSetWarning method getNextWarning. To retrieve subsequent warnings, call getNextWarning on each RowSetWarning object that is returned.

The inherited methods getMessage, getSQLState, and getErrorCode retrieve information contained in a RowSetWarning object.

An extension of SQLException that provides information
about database warnings set on RowSet objects.
Warnings are silently chained to the object whose method call
caused it to be reported.
This class complements the SQLWarning class.

Rowset warnings may be retrieved from JdbcRowSet,
CachedRowSet™,
WebRowSet, FilteredRowSet, or JoinRowSet
implementations. To retrieve the first warning reported on any
RowSet
implementation,  use the method getRowSetWarnings defined
in the JdbcRowSet interface or the CachedRowSet
interface. To retrieve a warning chained to the first warning, use the
RowSetWarning method
getNextWarning. To retrieve subsequent warnings, call
getNextWarning on each RowSetWarning object that is
returned.

The inherited methods getMessage, getSQLState,
and getErrorCode retrieve information contained in a
RowSetWarning object.
raw docstring

javax.sql.rowset.serial.core

No vars found in this namespace.

javax.sql.rowset.serial.SerialArray

A serialized version of an Array object, which is the mapping in the Java programming language of an SQL ARRAY value.

The SerialArray class provides a constructor for creating a SerialArray instance from an Array object, methods for getting the base type and the SQL name for the base type, and methods for copying all or part of a SerialArray object.

Note: In order for this class to function correctly, a connection to the data source must be available in order for the SQL Array object to be materialized (have all of its elements brought to the client server) if necessary. At this time, logical pointers to the data in the data source, such as locators, are not currently supported.

Thread safety

A SerialArray is not safe for use by multiple concurrent threads. If a SerialArray is to be used by more than one thread then access to the SerialArray should be controlled by appropriate synchronization.

A serialized version of an Array
object, which is the mapping in the Java programming language of an SQL
ARRAY value.

The SerialArray class provides a constructor for creating
a SerialArray instance from an Array object,
methods for getting the base type and the SQL name for the base type, and
methods for copying all or part of a SerialArray object.


Note: In order for this class to function correctly, a connection to the
data source
must be available in order for the SQL Array object to be
materialized (have all of its elements brought to the client server)
if necessary. At this time, logical pointers to the data in the data source,
such as locators, are not currently supported.

 Thread safety

A SerialArray is not safe for use by multiple concurrent threads.  If a
SerialArray is to be used by more than one thread then access to the
SerialArray should be controlled by appropriate synchronization.
raw docstring

javax.sql.rowset.serial.SerialBlob

A serialized mapping in the Java programming language of an SQL BLOB value.

The SerialBlob class provides a constructor for creating an instance from a Blob object. Note that the Blob object should have brought the SQL BLOB value's data over to the client before a SerialBlob object is constructed from it. The data of an SQL BLOB value can be materialized on the client as an array of bytes (using the method Blob.getBytes) or as a stream of uninterpreted bytes (using the method Blob.getBinaryStream).

SerialBlob methods make it possible to make a copy of a SerialBlob object as an array of bytes or as a stream. They also make it possible to locate a given pattern of bytes or a Blob object within a SerialBlob object and to update or truncate a Blob object.

Thread safety

A SerialBlob is not safe for use by multiple concurrent threads. If a SerialBlob is to be used by more than one thread then access to the SerialBlob should be controlled by appropriate synchronization.

A serialized mapping in the Java programming language of an SQL
BLOB value.

The SerialBlob class provides a constructor for creating
an instance from a Blob object.  Note that the
Blob
object should have brought the SQL BLOB value's data over
to the client before a SerialBlob object
is constructed from it.  The data of an SQL BLOB value can
be materialized on the client as an array of bytes (using the method
Blob.getBytes) or as a stream of uninterpreted bytes
(using the method Blob.getBinaryStream).

SerialBlob methods make it possible to make a copy of a
SerialBlob object as an array of bytes or as a stream.
They also make it possible to locate a given pattern of bytes or a
Blob object within a SerialBlob object
and to update or truncate a Blob object.

 Thread safety

 A SerialBlob is not safe for use by multiple concurrent threads.  If a
SerialBlob is to be used by more than one thread then access to the SerialBlob
should be controlled by appropriate synchronization.
raw docstring

javax.sql.rowset.serial.SerialClob

A serialized mapping in the Java programming language of an SQL CLOB value.

The SerialClob class provides a constructor for creating an instance from a Clob object. Note that the Clob object should have brought the SQL CLOB value's data over to the client before a SerialClob object is constructed from it. The data of an SQL CLOB value can be materialized on the client as a stream of Unicode characters.

SerialClob methods make it possible to get a substring from a SerialClob object or to locate the start of a pattern of characters.

Thread safety

A SerialClob is not safe for use by multiple concurrent threads. If a SerialClob is to be used by more than one thread then access to the SerialClob should be controlled by appropriate synchronization.

A serialized mapping in the Java programming language of an SQL
CLOB value.

The SerialClob class provides a constructor for creating
an instance from a Clob object.  Note that the Clob
object should have brought the SQL CLOB value's data over
to the client before a SerialClob object
is constructed from it.  The data of an SQL CLOB value can
be materialized on the client as a stream of Unicode characters.

SerialClob methods make it possible to get a substring
from a SerialClob object or to locate the start of
a pattern of characters.

 Thread safety

 A SerialClob is not safe for use by multiple concurrent threads.  If a
SerialClob is to be used by more than one thread then access to the SerialClob
should be controlled by appropriate synchronization.
raw docstring

javax.sql.rowset.serial.SerialDatalink

A serialized mapping in the Java programming language of an SQL DATALINK value. A DATALINK value references a file outside of the underlying data source that the data source manages.

RowSet implementations can use the method RowSet.getURL to retrieve a java.net.URL object, which can be used to manipulate the external data.

 java.net.URL url = rowset.getURL(1);

Thread safety

A SerialDatalink is not safe for use by multiple concurrent threads. If a SerialDatalink is to be used by more than one thread then access to the SerialDatalink should be controlled by appropriate synchronization.

A serialized mapping in the Java programming language of an SQL
DATALINK value. A DATALINK value
references a file outside of the underlying data source that the
data source manages.

RowSet implementations can use the method RowSet.getURL
to retrieve a java.net.URL object, which can be used
to manipulate the external data.


     java.net.URL url = rowset.getURL(1);

 Thread safety

A SerialDatalink is not safe for use by multiple concurrent threads.  If a
SerialDatalink is to be used by more than one thread then access to the
SerialDatalink should be controlled by appropriate synchronization.
raw docstring

javax.sql.rowset.serial.SerialException

Indicates and an error with the serialization or de-serialization of SQL types such as BLOB, CLOB, STRUCT or ARRAY in addition to SQL types such as DATALINK and JAVAOBJECT

Indicates and an error with the serialization or de-serialization of
SQL types such as BLOB, CLOB, STRUCT or ARRAY in
addition to SQL types such as DATALINK and JAVAOBJECT
raw docstring

javax.sql.rowset.serial.SerialJavaObject

A serializable mapping in the Java programming language of an SQL JAVA_OBJECT value. Assuming the Java object implements the Serializable interface, this class simply wraps the serialization process.

If however, the serialization is not possible because the Java object is not immediately serializable, this class will attempt to serialize all non-static members to permit the object state to be serialized. Static or transient fields cannot be serialized; an attempt to serialize them will result in a SerialException object being thrown.

Thread safety

A SerialJavaObject is not safe for use by multiple concurrent threads. If a SerialJavaObject is to be used by more than one thread then access to the SerialJavaObject should be controlled by appropriate synchronization.

A serializable mapping in the Java programming language of an SQL
JAVA_OBJECT value. Assuming the Java object
implements the Serializable interface, this class simply wraps the
serialization process.

If however, the serialization is not possible because
the Java object is not immediately serializable, this class will
attempt to serialize all non-static members to permit the object
state to be serialized.
Static or transient fields cannot be serialized; an attempt to serialize
them will result in a SerialException object being thrown.

 Thread safety

A SerialJavaObject is not safe for use by multiple concurrent threads.  If a
SerialJavaObject is to be used by more than one thread then access to the
SerialJavaObject should be controlled by appropriate synchronization.
raw docstring

javax.sql.rowset.serial.SerialRef

A serialized mapping of a Ref object, which is the mapping in the Java programming language of an SQL REF value.

The SerialRef class provides a constructor for creating a SerialRef instance from a Ref object and provides methods for getting and setting the Ref object.

Thread safety

A SerialRef is not safe for use by multiple concurrent threads. If a SerialRef is to be used by more than one thread then access to the SerialRef should be controlled by appropriate synchronization.

A serialized mapping of a Ref object, which is the mapping in the
Java programming language of an SQL REF value.

The SerialRef class provides a constructor  for
creating a SerialRef instance from a Ref
object and provides methods for getting and setting the Ref object.

 Thread safety

A SerialRef is not safe for use by multiple concurrent threads.  If a
SerialRef is to be used by more than one thread then access to the SerialRef
should be controlled by appropriate synchronization.
raw docstring

javax.sql.rowset.serial.SerialStruct

A serialized mapping in the Java programming language of an SQL structured type. Each attribute that is not already serialized is mapped to a serialized form, and if an attribute is itself a structured type, each of its attributes that is not already serialized is mapped to a serialized form.

In addition, the structured type is custom mapped to a class in the Java programming language if there is such a mapping, as are its attributes, if appropriate.

The SerialStruct class provides a constructor for creating an instance from a Struct object, a method for retrieving the SQL type name of the SQL structured type in the database, and methods for retrieving its attribute values.

Thread safety

A SerialStruct is not safe for use by multiple concurrent threads. If a SerialStruct is to be used by more than one thread then access to the SerialStruct should be controlled by appropriate synchronization.

A serialized mapping in the Java programming language of an SQL
structured type. Each attribute that is not already serialized
is mapped to a serialized form, and if an attribute is itself
a structured type, each of its attributes that is not already
serialized is mapped to a serialized form.

In addition, the structured type is custom mapped to a class in the
Java programming language if there is such a mapping, as are
its attributes, if appropriate.

The SerialStruct class provides a constructor for creating
an instance from a Struct object, a method for retrieving
the SQL type name of the SQL structured type in the database, and methods
for retrieving its attribute values.

 Thread safety

A SerialStruct is not safe for use by multiple concurrent threads.  If a
SerialStruct is to be used by more than one thread then access to the
SerialStruct should be controlled by appropriate synchronization.
raw docstring

javax.sql.rowset.serial.SQLInputImpl

An input stream used for custom mapping user-defined types (UDTs). An SQLInputImpl object is an input stream that contains a stream of values that are the attributes of a UDT.

This class is used by the driver behind the scenes when the method getObject is called on an SQL structured or distinct type that has a custom mapping; a programmer never invokes SQLInputImpl methods directly. They are provided here as a convenience for those who write RowSet implementations.

The SQLInputImpl class provides a set of reader methods analogous to the ResultSet getter methods. These methods make it possible to read the values in an SQLInputImpl object.

The method wasNull is used to determine whether the the last value read was SQL NULL. When the method getObject is called with an object of a class implementing the interface SQLData, the JDBC driver calls the method SQLData.getSQLType to determine the SQL type of the UDT being custom mapped. The driver creates an instance of SQLInputImpl, populating it with the attributes of the UDT. The driver then passes the input stream to the method SQLData.readSQL, which in turn calls the SQLInputImpl reader methods to read the attributes from the input stream.

An input stream used for custom mapping user-defined types (UDTs).
An SQLInputImpl object is an input stream that contains a
stream of values that are the attributes of a UDT.

This class is used by the driver behind the scenes when the method
getObject is called on an SQL structured or distinct type
that has a custom mapping; a programmer never invokes
SQLInputImpl methods directly. They are provided here as a
convenience for those who write RowSet implementations.

The SQLInputImpl class provides a set of
reader methods analogous to the ResultSet getter
methods.  These methods make it possible to read the values in an
SQLInputImpl object.

The method wasNull is used to determine whether the
the last value read was SQL NULL.
When the method getObject is called with an
object of a class implementing the interface SQLData,
the JDBC driver calls the method SQLData.getSQLType
to determine the SQL type of the UDT being custom mapped. The driver
creates an instance of SQLInputImpl, populating it with the
attributes of the UDT.  The driver then passes the input
stream to the method SQLData.readSQL, which in turn
calls the SQLInputImpl reader methods
to read the attributes from the input stream.
raw docstring

javax.sql.rowset.serial.SQLOutputImpl

The output stream for writing the attributes of a custom-mapped user-defined type (UDT) back to the database. The driver uses this interface internally, and its methods are never directly invoked by an application programmer.

When an application calls the method PreparedStatement.setObject, the driver checks to see whether the value to be written is a UDT with a custom mapping. If it is, there will be an entry in a type map containing the Class object for the class that implements SQLData for this UDT. If the value to be written is an instance of SQLData, the driver will create an instance of SQLOutputImpl and pass it to the method SQLData.writeSQL. The method writeSQL in turn calls the appropriate SQLOutputImpl.writeXXX methods to write data from the SQLData object to the SQLOutputImpl output stream as the representation of an SQL user-defined type.

The output stream for writing the attributes of a
custom-mapped user-defined type (UDT) back to the database.
The driver uses this interface internally, and its
methods are never directly invoked by an application programmer.

When an application calls the
method PreparedStatement.setObject, the driver
checks to see whether the value to be written is a UDT with
a custom mapping.  If it is, there will be an entry in a
type map containing the Class object for the
class that implements SQLData for this UDT.
If the value to be written is an instance of SQLData,
the driver will create an instance of SQLOutputImpl
and pass it to the method SQLData.writeSQL.
The method writeSQL in turn calls the
appropriate SQLOutputImpl.writeXXX methods
to write data from the SQLData object to
the SQLOutputImpl output stream as the
representation of an SQL user-defined type.
raw docstring

javax.sql.rowset.spi.core

No vars found in this namespace.

javax.sql.rowset.spi.SyncFactory

The Service Provider Interface (SPI) mechanism that generates SyncProvider instances to be used by disconnected RowSet objects. The SyncProvider instances in turn provide the javax.sql.RowSetReader object the RowSet object needs to populate itself with data and the javax.sql.RowSetWriter object it needs to propagate changes to its data back to the underlying data source.

Because the methods in the SyncFactory class are all static, there is only one SyncFactory object per Java VM at any one time. This ensures that there is a single source from which a RowSet implementation can obtain its SyncProvider implementation.

1.0 Overview The SyncFactory class provides an internal registry of available synchronization provider implementations (SyncProvider objects). This registry may be queried to determine which synchronization providers are available. The following line of code gets an enumeration of the providers currently registered.

java.util.Enumeration e = SyncFactory.getRegisteredProviders();

All standard RowSet implementations must provide at least two providers:

an optimistic provider for use with a CachedRowSet implementation or an implementation derived from it an XML provider, which is used for reading and writing XML, such as with WebRowSet objects

Note that the JDBC RowSet Implementations include the SyncProvider implementations RIOptimisticProvider and RIXmlProvider, which satisfy this requirement.

The SyncFactory class provides accessor methods to assist applications in determining which synchronization providers are currently registered with the SyncFactory.

Other methods let RowSet persistence providers be registered or de-registered with the factory mechanism. This allows additional synchronization provider implementations to be made available to RowSet objects at run time.

Applications can apply a degree of filtering to determine the level of synchronization that a SyncProvider implementation offers. The following criteria determine whether a provider is made available to a RowSet object:

If a particular provider is specified by a RowSet object, and the SyncFactory does not contain a reference to this provider, a SyncFactoryException is thrown stating that the synchronization provider could not be found.

If a RowSet implementation is instantiated with a specified provider and the specified provider has been properly registered, the requested provider is supplied. Otherwise a SyncFactoryException is thrown.

If a RowSet object does not specify a SyncProvider implementation and no additional SyncProvider implementations are available, the reference implementation providers are supplied.

2.0 Registering SyncProvider Implementations

Both vendors and developers can register SyncProvider implementations using one of the following mechanisms.

Using the command line The name of the provider is supplied on the command line, which will add the provider to the system properties. For example:

-Drowset.provider.classname=com.fred.providers.HighAvailabilityProvider Using the Standard Properties File The reference implementation is targeted to ship with J2SE 1.5, which will include an additional resource file that may be edited by hand. Here is an example of the properties file included in the reference implementation:

#Default JDBC RowSet sync providers listing

Optimistic synchronization provider

rowset.provider.classname.0=com.sun.rowset.providers.RIOptimisticProvider rowset.provider.vendor.0=Oracle Corporation rowset.provider.version.0=1.0

XML Provider using standard XML schema

rowset.provider.classname.1=com.sun.rowset.providers.RIXMLProvider rowset.provider.vendor.1=Oracle Corporation rowset.provider.version.1=1.0 The SyncFactory checks this file and registers the SyncProvider implementations that it contains. A developer or vendor can add other implementations to this file. For example, here is a possible addition:

rowset.provider.classname.2=com.fred.providers.HighAvailabilityProvider
rowset.provider.vendor.2=Fred, Inc.
rowset.provider.version.2=1.0

Using a JNDI Context Available providers can be registered on a JNDI context, and the SyncFactory will attempt to load SyncProvider implementations from that JNDI context. For example, the following code fragment registers a provider implementation on a JNDI context. This is something a deployer would normally do. In this example, MyProvider is being registered on a CosNaming namespace, which is the namespace used by J2EE resources.

import javax.naming.*;

Hashtable svrEnv = new Hashtable(); srvEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");

Context ctx = new InitialContext(svrEnv); com.fred.providers.MyProvider = new MyProvider(); ctx.rebind("providers/MyProvider", syncProvider);

Next, an application will register the JNDI context with the SyncFactory instance. This allows the SyncFactory to browse within the JNDI context looking for SyncProvider implementations.

Hashtable appEnv = new Hashtable(); appEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming"); appEnv.put(Context.PROVIDER_URL, "iiop://hostname/providers"); Context ctx = new InitialContext(appEnv);

SyncFactory.registerJNDIContext(ctx); If a RowSet object attempts to obtain a MyProvider object, the SyncFactory will try to locate it. First it searches for it in the system properties, then it looks in the resource files, and finally it checks the JNDI context that has been set. The SyncFactory instance verifies that the requested provider is a valid extension of the SyncProvider abstract class and then gives it to the RowSet object. In the following code fragment, a new CachedRowSet object is created and initialized with env, which contains the binding to MyProvider.

Hashtable env = new Hashtable(); env.put(SyncFactory.ROWSET_SYNC_PROVIDER, "com.fred.providers.MyProvider"); CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl(env); Further details on these mechanisms are available in the javax.sql.rowset.spi package specification.

The Service Provider Interface (SPI) mechanism that generates SyncProvider
instances to be used by disconnected RowSet objects.
The SyncProvider instances in turn provide the
javax.sql.RowSetReader object the RowSet object
needs to populate itself with data and the
javax.sql.RowSetWriter object it needs to
propagate changes to its
data back to the underlying data source.

Because the methods in the SyncFactory class are all static,
there is only one SyncFactory object
per Java VM at any one time. This ensures that there is a single source from which a
RowSet implementation can obtain its SyncProvider
implementation.

1.0 Overview
The SyncFactory class provides an internal registry of available
synchronization provider implementations (SyncProvider objects).
This registry may be queried to determine which
synchronization providers are available.
The following line of code gets an enumeration of the providers currently registered.


    java.util.Enumeration e = SyncFactory.getRegisteredProviders();
All standard RowSet implementations must provide at least two providers:

 an optimistic provider for use with a CachedRowSet implementation
    or an implementation derived from it
 an XML provider, which is used for reading and writing XML, such as with
      WebRowSet objects

Note that the JDBC RowSet Implementations include the SyncProvider
implementations RIOptimisticProvider and RIXmlProvider,
which satisfy this requirement.

The SyncFactory class provides accessor methods to assist
applications in determining which synchronization providers are currently
registered with the SyncFactory.

Other methods let RowSet persistence providers be
registered or de-registered with the factory mechanism. This
allows additional synchronization provider implementations to be made
available to RowSet objects at run time.

Applications can apply a degree of filtering to determine the level of
synchronization that a SyncProvider implementation offers.
The following criteria determine whether a provider is
made available to a RowSet object:

If a particular provider is specified by a RowSet object, and
the SyncFactory does not contain a reference to this provider,
a SyncFactoryException is thrown stating that the synchronization
provider could not be found.

If a RowSet implementation is instantiated with a specified
provider and the specified provider has been properly registered, the
requested provider is supplied. Otherwise a SyncFactoryException
is thrown.

If a RowSet object does not specify a
SyncProvider implementation and no additional
SyncProvider implementations are available, the reference
implementation providers are supplied.

2.0 Registering SyncProvider Implementations

Both vendors and developers can register SyncProvider
implementations using one of the following mechanisms.

Using the command line
The name of the provider is supplied on the command line, which will add
the provider to the system properties.
For example:


   -Drowset.provider.classname=com.fred.providers.HighAvailabilityProvider
Using the Standard Properties File
The reference implementation is targeted
to ship with J2SE 1.5, which will include an additional resource file
that may be edited by hand. Here is an example of the properties file
included in the reference implementation:


  #Default JDBC RowSet sync providers listing
  #

  # Optimistic synchronization provider
  rowset.provider.classname.0=com.sun.rowset.providers.RIOptimisticProvider
  rowset.provider.vendor.0=Oracle Corporation
  rowset.provider.version.0=1.0

  # XML Provider using standard XML schema
  rowset.provider.classname.1=com.sun.rowset.providers.RIXMLProvider
  rowset.provider.vendor.1=Oracle Corporation
  rowset.provider.version.1=1.0
The SyncFactory checks this file and registers the
SyncProvider implementations that it contains. A
developer or vendor can add other implementations to this file.
For example, here is a possible addition:


    rowset.provider.classname.2=com.fred.providers.HighAvailabilityProvider
    rowset.provider.vendor.2=Fred, Inc.
    rowset.provider.version.2=1.0

Using a JNDI Context
Available providers can be registered on a JNDI
context, and the SyncFactory will attempt to load
SyncProvider implementations from that JNDI context.
For example, the following code fragment registers a provider implementation
on a JNDI context.  This is something a deployer would normally do. In this
example, MyProvider is being registered on a CosNaming
namespace, which is the namespace used by J2EE resources.


   import javax.naming.*;

   Hashtable svrEnv = new  Hashtable();
   srvEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");

   Context ctx = new InitialContext(svrEnv);
   com.fred.providers.MyProvider = new MyProvider();
   ctx.rebind("providers/MyProvider", syncProvider);

Next, an application will register the JNDI context with the
SyncFactory instance.  This allows the SyncFactory
to browse within the JNDI context looking for SyncProvider
implementations.


   Hashtable appEnv = new Hashtable();
   appEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");
   appEnv.put(Context.PROVIDER_URL, "iiop://hostname/providers");
   Context ctx = new InitialContext(appEnv);

   SyncFactory.registerJNDIContext(ctx);
If a RowSet object attempts to obtain a MyProvider
object, the SyncFactory will try to locate it. First it searches
for it in the system properties, then it looks in the resource files, and
finally it checks the JNDI context that has been set. The SyncFactory
instance verifies that the requested provider is a valid extension of the
SyncProvider abstract class and then gives it to the
RowSet object. In the following code fragment, a new
CachedRowSet object is created and initialized with
env, which contains the binding to MyProvider.


   Hashtable env = new Hashtable();
   env.put(SyncFactory.ROWSET_SYNC_PROVIDER, "com.fred.providers.MyProvider");
   CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl(env);
Further details on these mechanisms are available in the
javax.sql.rowset.spi package specification.
raw docstring

javax.sql.rowset.spi.SyncFactoryException

Indicates an error with SyncFactory mechanism. A disconnected RowSet implementation cannot be used without a SyncProvider being successfully instantiated

Indicates an error with SyncFactory mechanism. A disconnected
RowSet implementation cannot be used  without a SyncProvider
being successfully instantiated
raw docstring

javax.sql.rowset.spi.SyncProvider

The synchronization mechanism that provides reader/writer capabilities for disconnected RowSet objects. A SyncProvider implementation is a class that extends the SyncProvider abstract class.

A SyncProvider implementation is identified by a unique ID, which is its fully qualified class name. This name must be registered with the SyncFactory SPI, thus making the implementation available to all RowSet implementations. The factory mechanism in the reference implementation uses this name to instantiate the implementation, which can then provide a RowSet object with its reader (a javax.sql.RowSetReader object) and its writer (a javax.sql.RowSetWriter object).

The Jdbc RowSet Implementations specification provides two reference implementations of the SyncProvider abstract class: RIOptimisticProvider and RIXMLProvider. The RIOptimisticProvider can set any RowSet implementation with a RowSetReader object and a RowSetWriter object. However, only the RIXMLProvider implementation can set an XmlReader object and an XmlWriter object. A WebRowSet object uses the XmlReader object to read data in XML format to populate itself with that data. It uses the XmlWriter object to write itself to a stream or java.io.Writer object in XML format.

1.0 Naming Convention for Implementations As a guide to naming SyncProvider implementations, the following should be noted:

The name for a SyncProvider implementation is its fully qualified class name. It is recommended that vendors supply a SyncProvider implementation in a package named providers.

For instance, if a vendor named Fred, Inc. offered a SyncProvider implementation, you could have the following:

Vendor name:  Fred, Inc.
Domain name of vendor:  com.fred
Package name:  com.fred.providers
SyncProvider implementation class name:  HighAvailabilityProvider

Fully qualified class name of SyncProvider implementation:
                   com.fred.providers.HighAvailabilityProvider

The following line of code uses the fully qualified name to register this implementation with the SyncFactory static instance.

SyncFactory.registerProvider(
                     "com.fred.providers.HighAvailabilityProvider");

The default SyncProvider object provided with the reference implementation uses the following name:

com.sun.rowset.providers.RIOptimisticProvider

A vendor can register a SyncProvider implementation class name with Oracle Corporation by sending email to jdbc@sun.com. Oracle will maintain a database listing the available SyncProvider implementations for use with compliant RowSet implementations. This database will be similar to the one already maintained to list available JDBC drivers.

Vendors should refer to the reference implementation synchronization providers for additional guidance on how to implement a new SyncProvider implementation.

2.0 How a RowSet Object Gets Its Provider

A disconnected Rowset object may get access to a SyncProvider object in one of the following two ways:

Using a constructor

  CachedRowSet crs = new CachedRowSet(
             "com.fred.providers.HighAvailabilitySyncProvider");

Using the setSyncProvider method

  CachedRowSet crs = new CachedRowSet();
  crs.setSyncProvider("com.fred.providers.HighAvailabilitySyncProvider");

By default, the reference implementations of the RowSet synchronization providers are always available to the Java platform. If no other pluggable synchronization providers have been correctly registered, the SyncFactory will automatically generate an instance of the default SyncProvider reference implementation. Thus, in the preceding code fragment, if no implementation named com.fred.providers.HighAvailabilitySyncProvider has been registered with the SyncFactory instance, crs will be assigned the default provider in the reference implementation, which is com.sun.rowset.providers.RIOptimisticProvider.

3.0 Violations and Synchronization Issues If an update between a disconnected RowSet object and a data source violates the original query or the underlying data source constraints, this will result in undefined behavior for all disconnected RowSet implementations and their designated SyncProvider implementations. Not defining the behavior when such violations occur offers greater flexibility for a SyncProvider implementation to determine its own best course of action.

A SyncProvider implementation may choose to implement a specific handler to handle a subset of query violations. However if an original query violation or a more general data source constraint violation is not handled by the SyncProvider implementation, all SyncProvider objects must throw a SyncProviderException.

4.0 Updatable SQL VIEWs It is possible for any disconnected or connected RowSet object to be populated from an SQL query that is formulated originally from an SQL VIEW. While in many cases it is possible for an update to be performed to an underlying view, such an update requires additional metadata, which may vary. The SyncProvider class provides two constants to indicate whether an implementation supports updating an SQL VIEW.

NONUPDATABLE_VIEW_SYNC - Indicates that a SyncProvider implementation does not support synchronization with an SQL VIEW as the underlying source of data for the RowSet object. UPDATABLE_VIEW_SYNC - Indicates that a SyncProvider implementation supports synchronization with an SQL VIEW as the underlying source of data.

The default is for a RowSet object not to be updatable if it was populated with data from an SQL VIEW.

5.0 SyncProvider Constants The SyncProvider class provides three sets of constants that are used as return values or parameters for SyncProvider methods. SyncProvider objects may be implemented to perform synchronization between a RowSet object and its underlying data source with varying degrees of of care. The first group of constants indicate how synchronization is handled. For example, GRADE_NONE indicates that a SyncProvider object will not take any care to see what data is valid and will simply write the RowSet data to the data source. GRADE_MODIFIED_AT_COMMIT indicates that the provider will check only modified data for validity. Other grades check all data for validity or set locks when data is modified or loaded.

Constants to indicate the synchronization grade of a SyncProvider object

SyncProvider.GRADE_NONE SyncProvider.GRADE_MODIFIED_AT_COMMIT SyncProvider.GRADE_CHECK_ALL_AT_COMMIT SyncProvider.GRADE_LOCK_WHEN_MODIFIED SyncProvider.GRADE_LOCK_WHEN_LOADED

Constants to indicate what locks are set on the data source

SyncProvider.DATASOURCE_NO_LOCK
SyncProvider.DATASOURCE_ROW_LOCK
SyncProvider.DATASOURCE_TABLE_LOCK
SyncProvider.DATASOURCE_DB_LOCK

Constants to indicate whether a SyncProvider object can perform updates to an SQL VIEW These constants are explained in the preceding section (4.0).

SyncProvider.UPDATABLE_VIEW_SYNC
SyncProvider.NONUPDATABLE_VIEW_SYNC
The synchronization mechanism that provides reader/writer capabilities for
disconnected RowSet objects.
A SyncProvider implementation is a class that extends the
SyncProvider abstract class.

A SyncProvider implementation is
identified by a unique ID, which is its fully qualified class name.
This name must be registered with the
SyncFactory SPI, thus making the implementation available to
all RowSet implementations.
The factory mechanism in the reference implementation uses this name to instantiate
the implementation, which can then provide a RowSet object with its
reader (a javax.sql.RowSetReader object) and its writer (a
javax.sql.RowSetWriter object).

The Jdbc RowSet Implementations specification provides two
reference implementations of the SyncProvider abstract class:
RIOptimisticProvider and RIXMLProvider.
The RIOptimisticProvider can set any RowSet
implementation with a RowSetReader object and a
RowSetWriter object.  However, only the RIXMLProvider
implementation can set an XmlReader object and an
XmlWriter object. A WebRowSet object uses the
XmlReader object to read data in XML format to populate itself with that
data.  It uses the XmlWriter object to write itself to a stream or
java.io.Writer object in XML format.

1.0 Naming Convention for Implementations
As a guide  to naming SyncProvider
implementations, the following should be noted:

The name for a SyncProvider implementation
is its fully qualified class name.
It is recommended that vendors supply a
SyncProvider implementation in a package named providers.


For instance, if a vendor named Fred, Inc. offered a
SyncProvider implementation, you could have the following:


    Vendor name:  Fred, Inc.
    Domain name of vendor:  com.fred
    Package name:  com.fred.providers
    SyncProvider implementation class name:  HighAvailabilityProvider

    Fully qualified class name of SyncProvider implementation:
                       com.fred.providers.HighAvailabilityProvider

The following line of code uses the fully qualified name to register
this implementation with the SyncFactory static instance.


    SyncFactory.registerProvider(
                         "com.fred.providers.HighAvailabilityProvider");

The default SyncProvider object provided with the reference
implementation uses the following name:


    com.sun.rowset.providers.RIOptimisticProvider

A vendor can register a SyncProvider implementation class name
with Oracle Corporation by sending email to jdbc@sun.com.
Oracle will maintain a database listing the
available SyncProvider implementations for use with compliant
RowSet implementations.  This database will be similar to the
one already maintained to list available JDBC drivers.

Vendors should refer to the reference implementation synchronization
providers for additional guidance on how to implement a new
SyncProvider implementation.

2.0 How a RowSet Object Gets Its Provider

A disconnected Rowset object may get access to a
SyncProvider object in one of the following two ways:

 Using a constructor


      CachedRowSet crs = new CachedRowSet(
                 "com.fred.providers.HighAvailabilitySyncProvider");
 Using the setSyncProvider method


      CachedRowSet crs = new CachedRowSet();
      crs.setSyncProvider("com.fred.providers.HighAvailabilitySyncProvider");



By default, the reference implementations of the RowSet synchronization
providers are always available to the Java platform.
If no other pluggable synchronization providers have been correctly
registered, the SyncFactory will automatically generate
an instance of the default SyncProvider reference implementation.
Thus, in the preceding code fragment, if no implementation named
com.fred.providers.HighAvailabilitySyncProvider has been
registered with the SyncFactory instance, crs will be
assigned the default provider in the reference implementation, which is
com.sun.rowset.providers.RIOptimisticProvider.

3.0 Violations and Synchronization Issues
If an update between a disconnected RowSet object
and a data source violates
the original query or the underlying data source constraints, this will
result in undefined behavior for all disconnected RowSet implementations
and their designated SyncProvider implementations.
Not defining the behavior when such violations occur offers greater flexibility
for a SyncProvider
implementation to determine its own best course of action.

A SyncProvider implementation
may choose to implement a specific handler to
handle a subset of query violations.
However if an original query violation or a more general data source constraint
violation is not handled by the SyncProvider implementation,
all SyncProvider
objects must throw a SyncProviderException.

4.0 Updatable SQL VIEWs
It is possible for any disconnected or connected RowSet object to be populated
from an SQL query that is formulated originally from an SQL VIEW.
While in many cases it is possible for an update to be performed to an
underlying view, such an update requires additional metadata, which may vary.
The SyncProvider class provides two constants to indicate whether
an implementation supports updating an SQL VIEW.

NONUPDATABLE_VIEW_SYNC - Indicates that a SyncProvider
implementation does not support synchronization with an SQL VIEW as the
underlying source of data for the RowSet object.
UPDATABLE_VIEW_SYNC - Indicates that a
SyncProvider implementation
supports synchronization with an SQL VIEW as the underlying source
of data.


The default is for a RowSet object not to be updatable if it was
populated with data from an SQL VIEW.

5.0 SyncProvider Constants
The SyncProvider class provides three sets of constants that
are used as return values or parameters for SyncProvider methods.
SyncProvider objects may be implemented to perform synchronization
between a RowSet object and its underlying data source with varying
degrees of of care. The first group of constants indicate how synchronization
is handled. For example, GRADE_NONE indicates that a
SyncProvider object will not take any care to see what data is
valid and will simply write the RowSet data to the data source.
GRADE_MODIFIED_AT_COMMIT indicates that the provider will check
only modified data for validity.  Other grades check all data for validity
or set locks when data is modified or loaded.

 Constants to indicate the synchronization grade of a
    SyncProvider object

   SyncProvider.GRADE_NONE
   SyncProvider.GRADE_MODIFIED_AT_COMMIT
   SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
   SyncProvider.GRADE_LOCK_WHEN_MODIFIED
   SyncProvider.GRADE_LOCK_WHEN_LOADED

 Constants to indicate what locks are set on the data source

    SyncProvider.DATASOURCE_NO_LOCK
    SyncProvider.DATASOURCE_ROW_LOCK
    SyncProvider.DATASOURCE_TABLE_LOCK
    SyncProvider.DATASOURCE_DB_LOCK

 Constants to indicate whether a SyncProvider object can
      perform updates to an SQL VIEW
      These constants are explained in the preceding section (4.0).

    SyncProvider.UPDATABLE_VIEW_SYNC
    SyncProvider.NONUPDATABLE_VIEW_SYNC
raw docstring

javax.sql.rowset.spi.SyncProviderException

Indicates an error with the SyncProvider mechanism. This exception is created by a SyncProvider abstract class extension if it encounters violations in reading from or writing to the originating data source.

If it is implemented to do so, the SyncProvider object may also create a SyncResolver object and either initialize the SyncProviderException object with it at construction time or set it with the SyncProvider object at a later time.

The method acceptChanges will throw this exception after the writer has finished checking for conflicts and has found one or more conflicts. An application may catch a SyncProviderException object and call its getSyncResolver method to get its SyncResolver object. See the code fragment in the interface comment for SyncResolver for an example. This SyncResolver object will mirror the RowSet object that generated the exception, except that it will contain only the values from the data source that are in conflict. All other values in the SyncResolver object will be null.

The SyncResolver object may be used to examine and resolve each conflict in a row and then go to the next row with a conflict to repeat the procedure.

A SyncProviderException object may or may not contain a description of the condition causing the exception. The inherited method getMessage may be called to retrieve the description if there is one.

Indicates an error with the SyncProvider mechanism. This exception
is created by a SyncProvider abstract class extension if it
encounters violations in reading from or writing to the originating data source.

If it is implemented to do so, the SyncProvider object may also create a
SyncResolver object and either initialize the SyncProviderException
object with it at construction time or set it with the SyncProvider object at
a later time.

The method acceptChanges will throw this exception after the writer
has finished checking for conflicts and has found one or more conflicts. An
application may catch a SyncProviderException object and call its
getSyncResolver method to get its SyncResolver object.
See the code fragment in the interface comment for
SyncResolver for an example.
This SyncResolver object will mirror the RowSet
object that generated the exception, except that it will contain only the values
from the data source that are in conflict.  All other values in the SyncResolver
object will be null.

The SyncResolver object may be used to examine and resolve
each conflict in a row and then go to the next row with a conflict to
repeat the procedure.

A SyncProviderException object may or may not contain a description of the
condition causing the exception.  The inherited method getMessage may be
called to retrieve the description if there is one.
raw docstring

javax.sql.rowset.spi.SyncResolver

Defines a framework that allows applications to use a manual decision tree to decide what should be done when a synchronization conflict occurs. Although it is not mandatory for applications to resolve synchronization conflicts manually, this framework provides the means to delegate to the application when conflicts arise.

Note that a conflict is a situation where the RowSet object's original values for a row do not match the values in the data source, which indicates that the data source row has been modified since the last synchronization. Note also that a RowSet object's original values are the values it had just prior to the the last synchronization, which are not necessarily its initial values.

Description of a SyncResolver Object

A SyncResolver object is a specialized RowSet object that implements the SyncResolver interface. It may operate as either a connected RowSet object (an implementation of the JdbcRowSet interface) or a connected RowSet object (an implementation of the CachedRowSet interface or one of its subinterfaces). For information on the subinterfaces, see the javax.sql.rowset package description. The reference implementation for SyncResolver implements the CachedRowSet interface, but other implementations may choose to implement the JdbcRowSet interface to satisfy particular needs.

After an application has attempted to synchronize a RowSet object with the data source (by calling the CachedRowSet method acceptChanges), and one or more conflicts have been found, a rowset's SyncProvider object creates an instance of SyncResolver. This new SyncResolver object has the same number of rows and columns as the RowSet object that was attempting the synchronization. The SyncResolver object contains the values from the data source that caused the conflict(s) and null for all other values. In addition, it contains information about each conflict.

Getting and Using a SyncResolver Object

When the method acceptChanges encounters conflicts, the SyncProvider object creates a SyncProviderException object and sets it with the new SyncResolver object. The method acceptChanges will throw this exception, which the application can then catch and use to retrieve the SyncResolver object it contains. The following code snippet uses the SyncProviderException method getSyncResolver to get the SyncResolver object resolver.

 catch (SyncProviderException spe) {
    SyncResolver resolver = spe.getSyncResolver();
...
}

}

With resolver in hand, an application can use it to get the information it contains about the conflict or conflicts. A SyncResolver object such as resolver keeps track of the conflicts for each row in which there is a conflict. It also places a lock on the table or tables affected by the rowset's command so that no more conflicts can occur while the current conflicts are being resolved.

The following kinds of information can be obtained from a SyncResolver object:

What operation was being attempted when a conflict occurred The SyncProvider interface defines four constants describing states that may occur. Three constants describe the type of operation (update, delete, or insert) that a RowSet object was attempting to perform when a conflict was discovered, and the fourth indicates that there is no conflict. These constants are the possible return values when a SyncResolver object calls the method getStatus.

 int operation = resolver.getStatus();

The value in the data source that caused a conflict A conflict exists when a value that a RowSet object has changed and is attempting to write to the data source has also been changed in the data source since the last synchronization. An application can call the SyncResolver method getConflictValue to retrieve the value in the data source that is the cause of the conflict because the values in a SyncResolver object are the conflict values from the data source.

java.lang.Object conflictValue = resolver.getConflictValue(2);

Note that the column in resolver can be designated by the column number, as is done in the preceding line of code, or by the column name.

With the information retrieved from the methods getStatus and getConflictValue, the application may make a determination as to which value should be persisted in the data source. The application then calls the SyncResolver method setResolvedValue, which sets the value to be persisted in the RowSet object and also in the data source.

resolver.setResolvedValue("DEPT", 8390426);

In the preceding line of code, the column name designates the column in the RowSet object that is to be set with the given value. The column number can also be used to designate the column.

An application calls the method setResolvedValue after it has resolved all of the conflicts in the current conflict row and repeats this process for each conflict row in the SyncResolver object.

Navigating a SyncResolver Object

Because a SyncResolver object is a RowSet object, an application can use all of the RowSet methods for moving the cursor to navigate a SyncResolver object. For example, an application can use the RowSet method next to get to each row and then call the SyncResolver method getStatus to see if the row contains a conflict. In a row with one or more conflicts, the application can iterate through the columns to find any non-null values, which will be the values from the data source that are in conflict.

To make it easier to navigate a SyncResolver object, especially when there are large numbers of rows with no conflicts, the SyncResolver interface defines the methods nextConflict and previousConflict, which move only to rows that contain at least one conflict value. Then an application can call the SyncResolver method getConflictValue, supplying it with the column number, to get the conflict value itself. The code fragment in the next section gives an example.

Code Example

The following code fragment demonstrates how a disconnected RowSet object crs might attempt to synchronize itself with the underlying data source and then resolve the conflicts. In the try block, crs calls the method acceptChanges, passing it the Connection object con. If there are no conflicts, the changes in crs are simply written to the data source. However, if there is a conflict, the method acceptChanges throws a SyncProviderException object, and the catch block takes effect. In this example, which illustrates one of the many ways a SyncResolver object can be used, the SyncResolver method nextConflict is used in a while loop. The loop will end when nextConflict returns false, which will occur when there are no more conflict rows in the SyncResolver object resolver. In This particular code fragment, resolver looks for rows that have update conflicts (rows with the status SyncResolver.UPDATE_ROW_CONFLICT), and the rest of this code fragment executes only for rows where conflicts occurred because crs was attempting an update.

After the cursor for resolver has moved to the next conflict row that has an update conflict, the method getRow indicates the number of the current row, and the cursor for the CachedRowSet object crs is moved to the comparable row in crs. By iterating through the columns of that row in both resolver and crs, the conflicting values can be retrieved and compared to decide which one should be persisted. In this code fragment, the value in crs is the one set as the resolved value, which means that it will be used to overwrite the conflict value in the data source.

try {

    crs.acceptChanges(con);

} catch (SyncProviderException spe) {

    SyncResolver resolver = spe.getSyncResolver();

    Object crsValue;  // value in the RowSet object
    Object resolverValue:  // value in the SyncResolver object
    Object resolvedValue:  // value to be persisted

    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
                    // which should be the resolved value (the value to persist)
                    resolvedValue = crsValue;

                    resolver.setResolvedValue(j, resolvedValue);
                 }
             }
         }
     }
 }
Defines a framework that allows applications to use a manual decision tree
to decide what should be done when a synchronization conflict occurs.
Although it is not mandatory for
applications to resolve synchronization conflicts manually, this
framework provides the means to delegate to the application when conflicts
arise.

Note that a conflict is a situation where the RowSet object's original
values for a row do not match the values in the data source, which indicates that
the data source row has been modified since the last synchronization. Note also that
a RowSet object's original values are the values it had just prior to the
the last synchronization, which are not necessarily its initial values.


Description of a SyncResolver Object

A SyncResolver object is a specialized RowSet object
that implements the SyncResolver interface.
It may operate as either a connected RowSet object (an
implementation of the JdbcRowSet interface) or a connected
RowSet object (an implementation of the
CachedRowSet interface or one of its subinterfaces). For information
on the subinterfaces, see the
javax.sql.rowset package
description. The reference implementation for SyncResolver implements
the CachedRowSet interface, but other implementations
may choose to implement the JdbcRowSet interface to satisfy
particular needs.

After an application has attempted to synchronize a RowSet object with
the data source (by calling the CachedRowSet
method acceptChanges), and one or more conflicts have been found,
a rowset's SyncProvider object creates an instance of
SyncResolver. This new SyncResolver object has
the same number of rows and columns as the
RowSet object that was attempting the synchronization. The
SyncResolver object contains the values from the data source that caused
the conflict(s) and null for all other values.
In addition, it contains information about each conflict.


Getting and Using a SyncResolver Object

When the method acceptChanges encounters conflicts, the
SyncProvider object creates a SyncProviderException
object and sets it with the new SyncResolver object. The method
acceptChanges will throw this exception, which
the application can then catch and use to retrieve the
SyncResolver object it contains. The following code snippet uses the
SyncProviderException method getSyncResolver to get
the SyncResolver object resolver.


     catch (SyncProviderException spe) {
        SyncResolver resolver = spe.getSyncResolver();
    ...
    }

}

With resolver in hand, an application can use it to get the information
it contains about the conflict or conflicts.  A SyncResolver object
such as resolver keeps
track of the conflicts for each row in which there is a conflict.  It also places a
lock on the table or tables affected by the rowset's command so that no more
conflicts can occur while the current conflicts are being resolved.

The following kinds of information can be obtained from a SyncResolver
object:

   What operation was being attempted when a conflict occurred
The SyncProvider interface defines four constants
describing states that may occur. Three
constants describe the type of operation (update, delete, or insert) that a
RowSet object was attempting to perform when a conflict was discovered,
and the fourth indicates that there is no conflict.
These constants are the possible return values when a SyncResolver object
calls the method getStatus.


     int operation = resolver.getStatus();

   The value in the data source that caused a conflict
A conflict exists when a value that a RowSet object has changed
and is attempting to write to the data source
has also been changed in the data source since the last synchronization.  An
application can call the SyncResolver method
getConflictValue to retrieve the
value in the data source that is the cause of the conflict because the values in a
SyncResolver object are the conflict values from the data source.


    java.lang.Object conflictValue = resolver.getConflictValue(2);
Note that the column in resolver can be designated by the column number,
as is done in the preceding line of code, or by the column name.

With the information retrieved from the methods getStatus and
getConflictValue, the application may make a determination as to
which value should be persisted in the data source. The application then calls the
SyncResolver method setResolvedValue, which sets the value
to be persisted in the RowSet object and also in the data source.


    resolver.setResolvedValue("DEPT", 8390426);
In the preceding line of code,
the column name designates the column in the RowSet object
that is to be set with the given value. The column number can also be used to
designate the column.

An application calls the method setResolvedValue after it has
resolved all of the conflicts in the current conflict row and repeats this process
for each conflict row in the SyncResolver object.


Navigating a SyncResolver Object

Because a SyncResolver object is a RowSet object, an
application can use all of the RowSet methods for moving the cursor
to navigate a SyncResolver object. For example, an application can
use the RowSet method next to get to each row and then
call the SyncResolver method getStatus to see if the row
contains a conflict.  In a row with one or more conflicts, the application can
iterate through the columns to find any non-null values, which will be the values
from the data source that are in conflict.

To make it easier to navigate a SyncResolver object, especially when
there are large numbers of rows with no conflicts, the SyncResolver
interface defines the methods nextConflict and
previousConflict, which move only to rows
that contain at least one conflict value. Then an application can call the
SyncResolver method getConflictValue, supplying it
with the column number, to get the conflict value itself. The code fragment in the
next section gives an example.

Code Example

The following code fragment demonstrates how a disconnected RowSet
object crs might attempt to synchronize itself with the
underlying data source and then resolve the conflicts. In the try
block, crs calls the method acceptChanges, passing it the
Connection object con.  If there are no conflicts, the
changes in crs are simply written to the data source.  However, if there
is a conflict, the method acceptChanges throws a
SyncProviderException object, and the
catch block takes effect.  In this example, which
illustrates one of the many ways a SyncResolver object can be used,
the SyncResolver method nextConflict is used in a
while loop. The loop will end when nextConflict returns
false, which will occur when there are no more conflict rows in the
SyncResolver object resolver. In This particular code fragment,
resolver looks for rows that have update conflicts (rows with the status
SyncResolver.UPDATE_ROW_CONFLICT), and the rest of this code fragment
executes only for rows where conflicts occurred because crs was attempting an
update.

After the cursor for resolver has moved to the next conflict row that
has an update conflict, the method getRow indicates the number of the
current row, and
the cursor for the CachedRowSet object crs is moved to
the comparable row in crs. By iterating
through the columns of that row in both resolver and crs, the conflicting
values can be retrieved and compared to decide which one should be persisted. In this
code fragment, the value in crs is the one set as the resolved value, which means
that it will be used to overwrite the conflict value in the data source.



    try {

        crs.acceptChanges(con);

    } catch (SyncProviderException spe) {

        SyncResolver resolver = spe.getSyncResolver();

        Object crsValue;  // value in the RowSet object
        Object resolverValue:  // value in the SyncResolver object
        Object resolvedValue:  // value to be persisted

        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
                        // which should be the resolved value (the value to persist)
                        resolvedValue = crsValue;

                        resolver.setResolvedValue(j, resolvedValue);
                     }
                 }
             }
         }
     }
raw docstring

javax.sql.rowset.spi.TransactionalWriter

A specialized interface that facilitates an extension of the standard SyncProvider abstract class so that it has finer grained transaction control.

If one or more disconnected RowSet objects are participating in a global transaction, they may wish to coordinate their synchronization commits to preserve data integrity and reduce the number of synchronization exceptions. If this is the case, an application should set the CachedRowSet constant COMMIT_ON_ACCEPT_CHANGES to false and use the commit and rollback methods defined in this interface to manage transaction boundaries.

A specialized interface that facilitates an extension of the standard
SyncProvider abstract class so that it has finer grained
transaction control.

If one or more disconnected RowSet objects are participating
in a global transaction, they may wish to coordinate their synchronization
commits to preserve data integrity and reduce the number of
synchronization exceptions. If this is the case, an application should set
the CachedRowSet constant COMMIT_ON_ACCEPT_CHANGES
to false and use the commit and rollback
methods defined in this interface to manage transaction boundaries.
raw docstring

javax.sql.rowset.spi.XmlReader

A specialized interface that facilitates an extension of the SyncProvider abstract class for XML orientated synchronization providers.

SyncProvider implementations that supply XML data reader capabilities such as output XML stream capabilities can implement this interface to provide standard XmlReader objects to WebRowSet implementations.

An XmlReader object is registered as the XML reader for a WebRowSet by being assigned to the rowset's xmlReader field. When the WebRowSet object's readXml method is invoked, it in turn invokes its XML reader's readXML method.

A specialized interface that facilitates an extension of the
SyncProvider abstract class for XML orientated
synchronization providers.

SyncProvider  implementations that supply XML data reader
capabilities such as output XML stream capabilities can implement this
interface to provide standard XmlReader objects to
WebRowSet implementations.

An XmlReader object is registered as the
XML reader for a WebRowSet by being assigned to the
rowset's xmlReader field. When the WebRowSet
object's readXml method is invoked, it in turn invokes
its XML reader's readXML method.
raw docstring

javax.sql.rowset.spi.XmlWriter

A specialized interface that facilitates an extension of the SyncProvider abstract class for XML orientated synchronization providers.

SyncProvider implementations that supply XML data writer capabilities such as output XML stream capabilities can implement this interface to provide standard XmlWriter objects to WebRowSet implementations.

Writing a WebRowSet object includes printing the rowset's data, metadata, and properties, all with the appropriate XML tags.

A specialized interface that facilitates an extension of the
SyncProvider abstract class for XML orientated
synchronization providers.

SyncProvider  implementations that supply XML data writer
capabilities such as output XML stream capabilities can implement this
interface to provide standard XmlWriter objects to
WebRowSet implementations.

Writing a WebRowSet object includes printing the
rowset's data, metadata, and properties, all with the
appropriate XML tags.
raw docstring

javax.sql.rowset.WebRowSet

The standard interface that all implementations of a WebRowSet must implement.

1.0 Overview The WebRowSetImpl provides the standard reference implementation, which may be extended if required.

The standard WebRowSet XML Schema definition is available at the following URI:

http://java.sun.com/xml/ns/jdbc/webrowset.xsd

It describes the standard XML document format required when describing a RowSet object in XML and must be used be all standard implementations of the WebRowSet interface to ensure interoperability. In addition, the WebRowSet schema uses specific SQL/XML Schema annotations, thus ensuring greater cross platform inter-operability. This is an effort currently under way at the ISO organization. The SQL/XML definition is available at the following URI:

http://standards.iso.org/iso/9075/2002/12/sqlxml

The schema definition describes the internal data of a RowSet object in three distinct areas:

properties - These properties describe the standard synchronization provider properties in addition to the more general RowSet properties.

metadata - This describes the metadata associated with the tabular structure governed by a WebRowSet object. The metadata described is closely aligned with the metadata accessible in the underlying java.sql.ResultSet interface.

data - This describes the original data (the state of data since the last population or last synchronization of the WebRowSet object) and the current data. By keeping track of the delta between the original data and the current data, a WebRowSet maintains the ability to synchronize changes in its data back to the originating data source.

2.0 WebRowSet States The following sections demonstrates how a WebRowSet implementation should use the XML Schema to describe update, insert, and delete operations and to describe the state of a WebRowSet object in XML.

2.1 State 1 - Outputting a WebRowSet Object to XML In this example, a WebRowSet object is created and populated with a simple 2 column, 5 row table from a data source. Having the 5 rows in a WebRowSet object makes it possible to describe them in XML. The metadata describing the various standard JavaBeans properties as defined in the RowSet interface plus the standard properties defined in the CachedRowSet™ interface provide key details that describe WebRowSet properties. Outputting the WebRowSet object to XML using the standard writeXml methods describes the internal properties as follows:

<properties> <command>select co1, col2 from test_table</command> <concurrency>1</concurrency> <datasource/> <escape-processing>true</escape-processing> <fetch-direction>0</fetch-direction> <fetch-size>0</fetch-size> <isolation-level>1</isolation-level> <key-columns/> <map/> <max-field-size>0</max-field-size> <max-rows>0</max-rows> <query-timeout>0</query-timeout> <read-only>false</read-only> <rowset-type>TRANSACTION_READ_UNCOMMITED</rowset-type> <show-deleted>false</show-deleted> <table-name/> <url>jdbc:thin:oracle</url> <sync-provider> <sync-provider-name>.com.rowset.provider.RIOptimisticProvider</sync-provider-name> <sync-provider-vendor>Oracle Corporation</sync-provider-vendor> <sync-provider-version>1.0</sync-provider-name> <sync-provider-grade>LOW</sync-provider-grade> <data-source-lock>NONE</data-source-lock> </sync-provider> </properties> The meta-data describing the make up of the WebRowSet is described in XML as detailed below. Note both columns are described between the column-definition tags.

<metadata> <column-count>2</column-count> <column-definition> <column-index>1</column-index> <auto-increment>false</auto-increment> <case-sensitive>true</case-sensitive> <currency>false</currency> <nullable>1</nullable> <signed>false</signed> <searchable>true</searchable> <column-display-size>10</column-display-size> <column-label>COL1</column-label> <column-name>COL1</column-name> <schema-name/> <column-precision>10</column-precision> <column-scale>0</column-scale> <table-name/> <catalog-name/> <column-type>1</column-type> <column-type-name>CHAR</column-type-name> </column-definition> <column-definition> <column-index>2</column-index> <auto-increment>false</auto-increment> <case-sensitive>false</case-sensitive> <currency>false</currency> <nullable>1</nullable> <signed>true</signed> <searchable>true</searchable> <column-display-size>39</column-display-size> <column-label>COL2</column-label> <column-name>COL2</column-name> <schema-name/> <column-precision>38</column-precision> <column-scale>0</column-scale> <table-name/> <catalog-name/> <column-type>3</column-type> <column-type-name>NUMBER</column-type-name> </column-definition> </metadata> Having detailed how the properties and metadata are described, the following details how the contents of a WebRowSet object is described in XML. Note, that this describes a WebRowSet object that has not undergone any modifications since its instantiation. A currentRow tag is mapped to each row of the table structure that the WebRowSet object provides. A columnValue tag may contain either the stringData or binaryData tag, according to the SQL type that the XML value is mapping back to. The binaryData tag contains data in the Base64 encoding and is typically used for BLOB and CLOB type data.

<data> <currentRow> <columnValue> firstrow </columnValue> <columnValue> 1 </columnValue> </currentRow> <currentRow> <columnValue> secondrow </columnValue> <columnValue> 2 </columnValue> </currentRow> <currentRow> <columnValue> thirdrow </columnValue> <columnValue> 3 </columnValue> </currentRow> <currentRow> <columnValue> fourthrow </columnValue> <columnValue> 4 </columnValue> </currentRow> </data> 2.2 State 2 - Deleting a Row Deleting a row in a WebRowSet object involves simply moving to the row to be deleted and then calling the method deleteRow, as in any other RowSet object. The following two lines of code, in which wrs is a WebRowSet object, delete the third row.

wrs.absolute(3);
wrs.deleteRow();

The XML description shows the third row is marked as a deleteRow, which eliminates the third row in the WebRowSet object.

<data> <currentRow> <columnValue> firstrow </columnValue> <columnValue> 1 </columnValue> </currentRow> <currentRow> <columnValue> secondrow </columnValue> <columnValue> 2 </columnValue> </currentRow> <deleteRow> <columnValue> thirdrow </columnValue> <columnValue> 3 </columnValue> </deleteRow> <currentRow> <columnValue> fourthrow </columnValue> <columnValue> 4 </columnValue> </currentRow> </data> 2.3 State 3 - Inserting a Row A WebRowSet object can insert a new row by moving to the insert row, calling the appropriate updater methods for each column in the row, and then calling the method insertRow.

wrs.moveToInsertRow(); wrs.updateString(1, "fifththrow"); wrs.updateString(2, "5"); wrs.insertRow(); The following code fragment changes the second column value in the row just inserted. Note that this code applies when new rows are inserted right after the current row, which is why the method next moves the cursor to the correct row. Calling the method acceptChanges writes the change to the data source.

wrs.moveToCurrentRow(); wrs.next(); wrs.updateString(2, "V"); wrs.acceptChanges(); Describing this in XML demonstrates where the Java code inserts a new row and then performs an update on the newly inserted row on an individual field.

<data> <currentRow> <columnValue> firstrow </columnValue> <columnValue> 1 </columnValue> </currentRow> <currentRow> <columnValue> secondrow </columnValue> <columnValue> 2 </columnValue> </currentRow> <currentRow> <columnValue> newthirdrow </columnValue> <columnValue> III </columnValue> </currentRow> <insertRow> <columnValue> fifthrow </columnValue> <columnValue> 5 </columnValue> <updateValue> V </updateValue> </insertRow> <currentRow> <columnValue> fourthrow </columnValue> <columnValue> 4 </columnValue> </currentRow> </date> 2.4 State 4 - Modifying a Row Modifying a row produces specific XML that records both the new value and the value that was replaced. The value that was replaced becomes the original value, and the new value becomes the current value. The following code moves the cursor to a specific row, performs some modifications, and updates the row when complete.

wrs.absolute(5); wrs.updateString(1, "new4thRow"); wrs.updateString(2, "IV"); wrs.updateRow(); In XML, this is described by the modifyRow tag. Both the original and new values are contained within the tag for original row tracking purposes.

<data> <currentRow> <columnValue> firstrow </columnValue> <columnValue> 1 </columnValue> </currentRow> <currentRow> <columnValue> secondrow </columnValue> <columnValue> 2 </columnValue> </currentRow> <currentRow> <columnValue> newthirdrow </columnValue> <columnValue> III </columnValue> </currentRow> <currentRow> <columnValue> fifthrow </columnValue> <columnValue> 5 </columnValue> </currentRow> <modifyRow> <columnValue> fourthrow </columnValue> <updateValue> new4thRow </updateValue> <columnValue> 4 </columnValue> <updateValue> IV </updateValue> </modifyRow> </data>

The standard interface that all implementations of a WebRowSet
must implement.

1.0 Overview
The WebRowSetImpl provides the standard
reference implementation, which may be extended if required.

The standard WebRowSet XML Schema definition is available at the following
URI:


http://java.sun.com/xml/ns/jdbc/webrowset.xsd


It describes the standard XML document format required when describing a
RowSet object in XML and must be used be all standard implementations
of the WebRowSet interface to ensure interoperability. In addition,
the WebRowSet schema uses specific SQL/XML Schema annotations,
thus ensuring greater cross
platform inter-operability. This is an effort currently under way at the ISO
organization. The SQL/XML definition is available at the following URI:


http://standards.iso.org/iso/9075/2002/12/sqlxml


The schema definition describes the internal data of a RowSet object
in three distinct areas:

properties - These properties describe the standard synchronization
provider properties in addition to the more general RowSet properties.

metadata - This describes the metadata associated with the tabular structure governed by a
WebRowSet object. The metadata described is closely aligned with the
metadata accessible in the underlying java.sql.ResultSet interface.

data - This describes the original data (the state of data since the
last population
or last synchronization of the WebRowSet object) and the current
data. By keeping track of the delta between the original data and the current data,
a WebRowSet maintains the ability to synchronize changes
in its data back to the originating data source.



2.0 WebRowSet States
The following sections demonstrates how a WebRowSet implementation
should use the XML Schema to describe update, insert, and delete operations
and to describe the state of a WebRowSet object in XML.

2.1 State 1 - Outputting a WebRowSet Object to XML
In this example, a WebRowSet object is created and populated with a simple 2 column,
5 row table from a data source. Having the 5 rows in a WebRowSet object
makes it possible to describe them in XML. The
metadata describing the various standard JavaBeans properties as defined
in the RowSet interface plus the standard properties defined in
the CachedRowSet™ interface
provide key details that describe WebRowSet
properties. Outputting the WebRowSet object to XML using the standard
writeXml methods describes the internal properties as follows:


<properties>
      <command>select co1, col2 from test_table</command>
     <concurrency>1</concurrency>
     <datasource/>
     <escape-processing>true</escape-processing>
     <fetch-direction>0</fetch-direction>
     <fetch-size>0</fetch-size>
     <isolation-level>1</isolation-level>
     <key-columns/>
     <map/>
     <max-field-size>0</max-field-size>
     <max-rows>0</max-rows>
     <query-timeout>0</query-timeout>
     <read-only>false</read-only>
     <rowset-type>TRANSACTION_READ_UNCOMMITED</rowset-type>
     <show-deleted>false</show-deleted>
     <table-name/>
     <url>jdbc:thin:oracle</url>
     <sync-provider>
             <sync-provider-name>.com.rowset.provider.RIOptimisticProvider</sync-provider-name>
             <sync-provider-vendor>Oracle Corporation</sync-provider-vendor>
             <sync-provider-version>1.0</sync-provider-name>
             <sync-provider-grade>LOW</sync-provider-grade>
             <data-source-lock>NONE</data-source-lock>
     </sync-provider>
</properties>
The meta-data describing the make up of the WebRowSet is described
in XML as detailed below. Note both columns are described between the
column-definition tags.


<metadata>
     <column-count>2</column-count>
     <column-definition>
             <column-index>1</column-index>
             <auto-increment>false</auto-increment>
             <case-sensitive>true</case-sensitive>
             <currency>false</currency>
             <nullable>1</nullable>
             <signed>false</signed>
             <searchable>true</searchable>
             <column-display-size>10</column-display-size>
             <column-label>COL1</column-label>
             <column-name>COL1</column-name>
             <schema-name/>
             <column-precision>10</column-precision>
             <column-scale>0</column-scale>
             <table-name/>
             <catalog-name/>
             <column-type>1</column-type>
             <column-type-name>CHAR</column-type-name>
     </column-definition>
     <column-definition>
             <column-index>2</column-index>
             <auto-increment>false</auto-increment>
             <case-sensitive>false</case-sensitive>
             <currency>false</currency>
             <nullable>1</nullable>
             <signed>true</signed>
             <searchable>true</searchable>
             <column-display-size>39</column-display-size>
             <column-label>COL2</column-label>
             <column-name>COL2</column-name>
             <schema-name/>
             <column-precision>38</column-precision>
             <column-scale>0</column-scale>
             <table-name/>
             <catalog-name/>
             <column-type>3</column-type>
             <column-type-name>NUMBER</column-type-name>
     </column-definition>
</metadata>
Having detailed how the properties and metadata are described, the following details
how the contents of a WebRowSet object is described in XML. Note, that
this describes a WebRowSet object that has not undergone any
modifications since its instantiation.
A currentRow tag is mapped to each row of the table structure that the
WebRowSet object provides. A columnValue tag may contain
either the stringData or binaryData tag, according to
the SQL type that
the XML value is mapping back to. The binaryData tag contains data in the
Base64 encoding and is typically used for BLOB and CLOB type data.


<data>
     <currentRow>
             <columnValue>
                     firstrow
             </columnValue>
             <columnValue>
                     1
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     secondrow
             </columnValue>
             <columnValue>
                     2
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     thirdrow
             </columnValue>
             <columnValue>
                     3
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     fourthrow
             </columnValue>
             <columnValue>
                     4
             </columnValue>
     </currentRow>
</data>
2.2 State 2 - Deleting a Row
Deleting a row in a WebRowSet object involves simply moving to the row
to be deleted and then calling the method deleteRow, as in any other
RowSet object.  The following
two lines of code, in which wrs is a WebRowSet object, delete
the third row.


    wrs.absolute(3);
    wrs.deleteRow();
The XML description shows the third row is marked as a deleteRow,
 which eliminates the third row in the WebRowSet object.


<data>
     <currentRow>
             <columnValue>
                     firstrow
             </columnValue>
             <columnValue>
                     1
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     secondrow
             </columnValue>
             <columnValue>
                     2
             </columnValue>
     </currentRow>
     <deleteRow>
             <columnValue>
                     thirdrow
             </columnValue>
             <columnValue>
                     3
             </columnValue>
     </deleteRow>
     <currentRow>
             <columnValue>
                     fourthrow
             </columnValue>
             <columnValue>
                     4
             </columnValue>
     </currentRow>
</data>
2.3 State 3 - Inserting a Row
A WebRowSet object can insert a new row by moving to the insert row,
calling the appropriate updater methods for each column in the row, and then
calling the method insertRow.


wrs.moveToInsertRow();
wrs.updateString(1, "fifththrow");
wrs.updateString(2, "5");
wrs.insertRow();
The following code fragment changes the second column value in the row just inserted.
Note that this code applies when new rows are inserted right after the current row,
which is why the method next moves the cursor to the correct row.
Calling the method acceptChanges writes the change to the data source.



 wrs.moveToCurrentRow();
wrs.next();
wrs.updateString(2, "V");
wrs.acceptChanges();
Describing this in XML demonstrates where the Java code inserts a new row and then
performs an update on the newly inserted row on an individual field.


<data>
     <currentRow>
             <columnValue>
                     firstrow
             </columnValue>
             <columnValue>
                     1
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     secondrow
             </columnValue>
             <columnValue>
                     2
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     newthirdrow
             </columnValue>
             <columnValue>
                     III
             </columnValue>
     </currentRow>
     <insertRow>
             <columnValue>
                     fifthrow
             </columnValue>
             <columnValue>
                     5
             </columnValue>
             <updateValue>
                     V
             </updateValue>
     </insertRow>
     <currentRow>
             <columnValue>
                     fourthrow
             </columnValue>
             <columnValue>
                     4
             </columnValue>
     </currentRow>
</date>
2.4 State 4 - Modifying a Row
Modifying a row produces specific XML that records both the new value and the
value that was replaced.  The value that was replaced becomes the original value,
and the new value becomes the current value. The following
code moves the cursor to a specific row, performs some modifications, and updates
the row when complete.


wrs.absolute(5);
wrs.updateString(1, "new4thRow");
wrs.updateString(2, "IV");
wrs.updateRow();
In XML, this is described by the modifyRow tag. Both the original and new
values are contained within the tag for original row tracking purposes.


<data>
     <currentRow>
             <columnValue>
                     firstrow
             </columnValue>
             <columnValue>
                     1
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     secondrow
             </columnValue>
             <columnValue>
                     2
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     newthirdrow
             </columnValue>
             <columnValue>
                     III
             </columnValue>
     </currentRow>
     <currentRow>
             <columnValue>
                     fifthrow
             </columnValue>
             <columnValue>
                     5
             </columnValue>
     </currentRow>
     <modifyRow>
             <columnValue>
                     fourthrow
             </columnValue>
             <updateValue>
                     new4thRow
             </updateValue>
             <columnValue>
                     4
             </columnValue>
             <updateValue>
                     IV
             </updateValue>
     </modifyRow>
</data>
raw docstring

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close