使用 JdbcRowSet 对象
原文: https://docs.oracle.com/javase/tutorial/jdbc/basics/jdbcrowset.html
JdbcRowSet
对象是增强的ResultSet
对象。它保持与其数据源的连接,就像ResultSet
对象一样。最大的区别在于它具有一组属性和一个监听器通知机制,使其成为 JavaBeans 组件。
JdbcRowSet
对象的一个主要用途是使ResultSet
对象在没有这些功能的情况下可滚动和可更新。
本节包括以下主题:
您可以通过各种方式创建JdbcRowSet
对象:
- 通过使用带有
ResultSet
对象的引用实现构造器 - 通过使用带有
Connection
对象的引用实现构造器 - 通过使用引用实现默认构造器
- 通过使用从
RowSetProvider
类创建的RowSetFactory
实例
注意:或者,您可以使用 JDBC 驱动程序的JdbcRowSet
实现中的构造器。但是,RowSet
接口的实现将与参考实现不同。这些实现将具有不同的名称和构造器。例如,Oracle JDBC 驱动程序的JdbcRowSet
接口实现名为oracle.jdbc.rowset.OracleJDBCRowSet
。
创建JdbcRowSet
对象的最简单方法是生成ResultSet
对象并将其传递给JdbcRowSetImpl
构造器。这样做不仅可以创建JdbcRowSet
对象,还可以使用ResultSet
对象中的数据填充它。
注:传递给JdbcRowSetImpl
构造器的ResultSet
对象必须是可滚动的。
例如,以下代码片段使用Connection
对象con
创建Statement
对象stmt
,然后执行查询。该查询生成ResultSet
对象rs
,该对象被传递给构造器以创建使用rs
中的数据初始化的新JdbcRowSet
对象:
stmt = con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("select * from COFFEES");
jdbcRs = new JdbcRowSetImpl(rs);
使用ResultSet
对象创建的JdbcRowSet
对象用作ResultSet
对象的包装。因为RowSet
对象rs
是可滚动和可更新的,所以jdbcRs
也是可滚动和可更新的。如果你运行没有任何参数的方法createStatement
,rs
将不可滚动或可更新,jdbcRs
也不会。
以下代码摘录自 JdbcRowSetSample
的第一个语句创建了一个JdbcRowSet
对象,该对象使用Connection
对象con
连接到数据库:
jdbcRs = new JdbcRowSetImpl(con);
jdbcRs.setCommand("select * from COFFEES");
jdbcRs.execute();
在使用方法setCommand
指定 SQL 语句之前,对象jdbcRs
不包含任何数据,然后运行方法execute
。
对象jdbcRs
是可滚动和可更新的;默认情况下,除非另有说明,否则JdbcRowSet
和所有其他RowSet
对象都是可滚动和可更新的。有关您可以指定的JdbcRowSet
属性的更多信息,请参见默认 JdbcRowSet 对象。
使用默认构造器
以下代码摘录中的第一个语句创建一个空的JdbcRowSet
对象。
public void createJdbcRowSet(String username, String password) {
jdbcRs = new JdbcRowSetImpl();
jdbcRs.setCommand("select * from COFFEES");
jdbcRs.setUrl("jdbc:myDriver:myAttribute");
jdbcRs.setUsername(username);
jdbcRs.setPassword(password);
jdbcRs.execute();
// ...
}
在使用方法setCommand
指定 SQL 语句,指定JdbcResultSet
对象如何连接数据库,然后运行方法execute
之前,对象jdbcRs
不包含任何数据。
所有参考实现构造器都为 Default JdbcRowSet Objects 部分中列出的属性分配默认值。
使用 RowSet 1.1(它是 Java SE 7 及更高版本的一部分),您可以使用RowSetFactory
的实例来创建JdbcRowSet
对象。例如,以下代码摘录使用RowSetFactory
接口的实例来创建JdbcRowSet
对象,jdbcRs
:
public void createJdbcRowSetWithRowSetFactory(
String username, String password)
throws SQLException {
RowSetFactory myRowSetFactory = null;
JdbcRowSet jdbcRs = null;
ResultSet rs = null;
Statement stmt = null;
try {
myRowSetFactory = RowSetProvider.newFactory();
jdbcRs = myRowSetFactory.createJdbcRowSet();
jdbcRs.setUrl("jdbc:myDriver:myAttribute");
jdbcRs.setUsername(username);
jdbcRs.setPassword(password);
jdbcRs.setCommand("select * from COFFEES");
jdbcRs.execute();
// ...
}
}
以下语句使用默认RowSetFactory
实现创建RowSetProvider
对象myRowSetFactory
,com.sun.rowset.RowSetFactoryImpl
:
myRowSetFactory = RowSetProvider.newFactory();
或者,如果 JDBC 驱动程序具有自己的RowSetFactory
实现,则可以将其指定为newFactory
方法的参数。
以下语句创建JdbcRowSet
对象jdbcRs
并配置其数据库连接属性:
jdbcRs = myRowSetFactory.createJdbcRowSet();
jdbcRs.setUrl("jdbc:myDriver:myAttribute");
jdbcRs.setUsername(username);
jdbcRs.setPassword(password);
RowSetFactory
接口包含创建 RowSet 1.1 及更高版本中可用的不同类型RowSet
实现的方法:
createCachedRowSet
createFilteredRowSet
createJdbcRowSet
createJoinRowSet
createWebRowSet
使用默认构造器创建JdbcRowSet
对象时,新的JdbcRowSet
对象将具有以下属性:
type
:ResultSet.TYPE_SCROLL_INSENSITIVE
(有可滚动的光标)concurrency
:ResultSet.CONCUR_UPDATABLE
(可更新)escapeProcessing
:true
(驱动程序将执行转义处理;启用转义处理时,驱动程序将扫描任何转义语法并将其转换为特定数据库可识别的代码)maxRows
:0
(行数无限制)maxFieldSize
:0
(列值的字节数没有限制;仅适用于存储BINARY
,VARBINARY
,LONGVARBINARY
,CHAR
,VARCHAR
和LONGVARCHAR
的列值)queryTimeout
:0
(没有时间限制执行查询所需的时间)showDeleted
:false
(删除的行不可见)transactionIsolation
:Connection.TRANSACTION_READ_COMMITTED
(仅读取已提交的数据)typeMap
:null
(与RowSet
对象使用的Connection
对象关联的类型映射为null
)
从这个列表中你必须记住的主要事情是JdbcRowSet
和所有其他RowSet
对象是可滚动和可更新的,除非你为这些属性设置不同的值。
默认 JdbcRowSet 对象部分列出了创建新JdbcRowSet
对象时默认设置的属性。如果使用默认构造器,则必须先设置一些其他属性,然后才能使用数据填充新的JdbcRowSet
对象。
为了获取其数据,JdbcRowSet
对象首先需要连接到数据库。以下四个属性包含用于获取与数据库的连接的信息。
username
:用户提供给数据库的名称,作为获取访问权限的一部分password
:用户的数据库密码url
:用户想要连接的数据库的 JDBC URLdatasourceName
:用于检索已使用 JNDI 命名服务注册的DataSource
对象的名称
您设置的这些属性中的哪一个取决于您要如何建立连接。首选方法是使用DataSource
对象,但使用 JNDI 命名服务注册DataSource
对象可能不实用,这通常由系统管理员完成。因此,代码示例都使用DriverManager
机制来获取连接,您使用url
属性而不是datasourceName
属性。
您必须设置的另一个属性是command
属性。此属性是确定JdbcRowSet
对象将包含哪些数据的查询。例如,以下代码行使用查询设置command
属性,该查询生成包含表COFFEES
中所有数据的ResultSet
对象:
jdbcRs.setCommand("select * from COFFEES");
设置command
属性和建立连接所需的属性后,可以通过调用execute
方法用数据填充jdbcRs
对象。
jdbcRs.execute();
execute
方法在后台为您做了很多事情:
- 它使用您分配给
url
,username
和password
属性的值建立与数据库的连接。 - 它执行您在
command
属性中设置的查询。 - 它将生成的
ResultSet
对象中的数据读入jdbcRs
对象。
更新,插入和删除JdbcRowSet
对象中的行的方式与更新,插入和删除可更新ResultSet
对象中的行的方式相同。同样,您导航JdbcRowSet
对象的方式与导航可滚动ResultSet
对象的方式相同。
咖啡馆的 Coffee Break 连锁店获得了另一家咖啡馆连锁店,现在拥有一个不支持滚动或更新结果集的遗留数据库。换句话说,此遗留数据库生成的任何ResultSet
对象都没有可滚动的游标,并且其中的数据无法修改。但是,通过创建使用ResultSet
对象中的数据填充的JdbcRowSet
对象,实际上可以使ResultSet
对象可滚动和可更新。
如前所述,JdbcRowSet
对象默认是可滚动和可更新的。因为其内容与ResultSet
对象中的内容相同,所以在JdbcRowSet
对象上操作相当于在ResultSet
对象上操作。并且由于JdbcRowSet
对象与数据库之间存在持续连接,因此对数据库中的数据也会对其自身数据进行更改。
本节包括以下主题:
不可滚动的ResultSet
对象只能使用next
方法向前移动光标,并且只能将光标从第一行向前移动到最后一行。但是,默认的JdbcRowSet
对象可以使用ResultSet
接口中定义的所有光标移动方法。
JdbcRowSet
对象可以调用方法next
,它也可以调用任何其他ResultSet
光标移动方法。例如,以下代码行将光标移动到jdbcRs
对象中的第四行,然后返回到第三行:
jdbcRs.absolute(4);
jdbcRs.previous();
方法previous
类似于方法next
,因为它可以在while
循环中用于按顺序遍历所有行。不同之处在于您必须将光标移动到最后一行之后的位置,previous
将光标移向开头。
您更新JdbcRowSet
对象中的数据的方式与更新ResultSet
对象中的数据的方式相同。
假设咖啡休息所有者想要提高一磅 Espresso 咖啡的价格。如果所有者知道 Espresso 位于jdbcRs
对象的第三行,则执行此操作的代码可能如下所示:
jdbcRs.absolute(3);
jdbcRs.updateFloat("PRICE", 10.99f);
jdbcRs.updateRow();
代码将光标移动到第三行,并将列PRICE
的值更改为 10.99,然后使用新价格更新数据库。
调用方法updateRow
会更新数据库,因为jdbcRs
已保持与数据库的连接。对于断开连接的RowSet
对象,情况有所不同。
如果 Coffee Break 连锁店的所有者想要将一种或多种咖啡添加到他提供的产品中,那么所有者将需要在每个新咖啡的COFFEES
表中添加一行,如下面的代码片段所示。 ] [JdbcRowSetSample]($docs-gettingstarted.html)
。请注意,因为jdbcRs
对象始终连接到数据库,所以在JdbcRowSet
对象中插入行与在ResultSet
对象中插入行相同:将光标移动到插入行,使用适当的 updater 方法为每列设置一个值,并调用方法insertRow
:
jdbcRs.moveToInsertRow();
jdbcRs.updateString("COF_NAME", "HouseBlend");
jdbcRs.updateInt("SUP_ID", 49);
jdbcRs.updateFloat("PRICE", 7.99f);
jdbcRs.updateInt("SALES", 0);
jdbcRs.updateInt("TOTAL", 0);
jdbcRs.insertRow();
jdbcRs.moveToInsertRow();
jdbcRs.updateString("COF_NAME", "HouseDecaf");
jdbcRs.updateInt("SUP_ID", 49);
jdbcRs.updateFloat("PRICE", 8.99f);
jdbcRs.updateInt("SALES", 0);
jdbcRs.updateInt("TOTAL", 0);
jdbcRs.insertRow();
当您调用方法insertRow
时,新行将插入jdbcRs
对象并插入到数据库中。前面的代码片段经过两次这个过程,因此在jdbcRs
对象和数据库中插入了两个新行。
与更新数据和插入新行一样,删除行对于JdbcRowSet
对象与ResultSet
对象相同。店主想要停止销售法国烤无咖啡因咖啡,这是jdbcRs
对象的最后一行。在以下代码行中,第一行将光标移动到最后一行,第二行删除jdbcRs
对象和数据库中的最后一行:
jdbcRs.last();
jdbcRs.deleteRow();
样例[JdbcRowSetSample]($docs-gettingstarted.html)
执行以下操作:
- 创建一个新的
JdbcRowSet
对象,该对象使用ResultSet
对象初始化,该对象是由执行检索COFFEES
表中的所有行的查询生成的 - 将光标移动到
COFFEES
表的第三行并更新该行中的PRICE
列 - 插入两个新行,一个用于
HouseBlend
,另一个用于HouseDecaf
- 将光标移动到最后一行并删除它