The RowSet Interface

by Thomas Paul

One of the problems with JDBC is the lack of support for using the rows returned from a database in a way that makes them accessible without maintaining a connection to the database. The RowSet interface was added to J2SE 1.4 to respond to this problem. The API for that version did not include any implementations of this interface although several sample implementations have been included as part of the early release program. J2SE 1.5 will include five standard implementations of the RowSet interface. In this article I would like to answer some questions about what RowSets are and how they might be used and take an advanced look at the upcoming implementations.

Q: What is a RowSet?

A: A RowSet is a disconnected, serializable version of a JDBC ResultSet.

Q: Could you explain that a little more clearly?

A: One of the problems with working with a ResultSet is that you can't pass it around from class to class across a network or across the Internet. A ResultSet maintains a connection to a database and because of that it can't be serialized. There are many situations where it would be a nice feature to be able to pass a ResultSet from one Java class to another across a network.

Suppose you had a client that invokes a server process to get some rows from a database. This might be an applet accessing a servlet or a JavaBean invoking a J2EE session bean. The server process would create a ResultSet and then it would have to read the data from the ResultSet and load it into some type of Collection object or array. Of course, you might want to include the metadata from the request (column names, display lengths, etc.) so you would need to figure out some way to pass that as well. However, no matter how you solved that problem it wouldn't be a standard solution.

The RowSet could be used in place of creating that Collection object and worrying about how to pass metadata. The RowSet extends the ResultSet interface so it has all the methods of ResultSet. The RowSet can be serialized because it doesn't have a connection to any database. When you run the execute method of the RowSet, all the data from the query is loaded into the RowSet and the connection is closed. The RowSet is a disconnected object in that it does not need to be connected to the database in order to provide data. Since it is disconnected it can be passed across a network.

Q: Will a RowSet have all the functionality of a ResultSet such as scrolling and updating?

A: Absolutely! In fact, you can take your RowSet, scroll through it, update it, store it in a file, load it back from the file at a later date, and use it to update the database.

Q: So why do I need ResultSet?

A: There is an obvious limitation at work here. The ResultSet does not contain all the data from your query. Since it has a connection to the database, when you run the next() method if the ResultSet needs more data it can go to the database and get it. The RowSet can't do that since it isn't connected to the database so it must load and hold all the data from your query as soon as you run the execute() method. If your query returns a lot or rows you could encounter very slow processing and out of memory errors. However, if the number of rows to be returned is a reasonable number then a RowSet can be used.

Q: Wait a minute. You said that the API would be supplying five standard implementations of the RowSet. Why are we getting standard implementations of RowSet when none of the other interfaces in the API have standard implementations?

A: The RowSet is different than other JDBC interfaces in that you can write a RowSet to be vendor neutral. A third party could write a RowSet implementation that could be used with any JDBC-compliant database. The standard implementation supplied by Sun uses a ResultSet to read the rows from a database and then stores those rows as Row objects in a Vector inside the RowSet. In fact, a RowSet implementation could be written to get its data from any source. The only requirement is that the RowSet acts as if it was a ResultSet. Of course, there is no reason that a vendor couldn't write a RowSet implementation that is vendor specific.

Q: So what are these five standard implementations?

A: The standard implementations have been designed to provide a fairly good range of functionality. The implementations provided are:

CachedRowSetImpl - This is the implementation of the RowSet that is closest to the definition of RowSet functionality that we discussed earlier. There are two ways to load this RowSet. The execute( ) method will load the RowSet using a Connection object. The populate( ) method will load the RowSet from a previously loaded ResultSet.

WebRowSetImpl - This is very similar to the CachedRowSetImpl (it is a child class) but it also includes methods for converting the rows into an XML document and loading the RowSet with an XML document. The XML document can come from any Stream or Reader/Writer object. This could be especially useful for Web Services.

JdbcRowSetImpl - This is a different style of implementation that is probably less useful in normal circumstances. The purpose of this RowSet is to make a ResultSet look like a JavaBean. It is not serializable and it must maintain a connection to the database.

The remaining two implementations are used with the first three implementations:

FilteredRowSetImpl - This is used to filter data from an existing RowSet. The filter will skip records that don't match the criteria specified in the filter when a next() is used on the RowSet.

JoinRowSetImpl - This is used to simulate a SQL join command between two or more RowSet objects.

Q: Where can I find these standard implementations?

A: As of October 2003, these are available as "Public Review Draft" versions and can be downloaded from here: http://java.sun.com/products/jdbc/download.html