使用 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对象:

  1. stmt = con.createStatement(
  2. ResultSet.TYPE_SCROLL_SENSITIVE,
  3. ResultSet.CONCUR_UPDATABLE);
  4. rs = stmt.executeQuery("select * from COFFEES");
  5. jdbcRs = new JdbcRowSetImpl(rs);

使用ResultSet对象创建的JdbcRowSet对象用作ResultSet对象的包装。因为RowSet对象rs是可滚动和可更新的,所以jdbcRs也是可滚动和可更新的。如果你运行没有任何参数的方法createStatementrs将不可滚动或可更新,jdbcRs也不会。

以下代码摘录自 JdbcRowSetSample 的第一个语句创建了一个JdbcRowSet对象,该对象使用Connection对象con连接到数据库:

  1. jdbcRs = new JdbcRowSetImpl(con);
  2. jdbcRs.setCommand("select * from COFFEES");
  3. jdbcRs.execute();

在使用方法setCommand指定 SQL 语句之前,对象jdbcRs不包含任何数据,然后运行方法execute

对象jdbcRs是可滚动和可更新的;默认情况下,除非另有说明,否则JdbcRowSet和所有其他RowSet对象都是可滚动和可更新的。有关您可以指定的JdbcRowSet属性的更多信息,请参见默认 JdbcRowSet 对象

使用默认构造器

以下代码摘录中的第一个语句创建一个空的JdbcRowSet对象。

  1. public void createJdbcRowSet(String username, String password) {
  2. jdbcRs = new JdbcRowSetImpl();
  3. jdbcRs.setCommand("select * from COFFEES");
  4. jdbcRs.setUrl("jdbc:myDriver:myAttribute");
  5. jdbcRs.setUsername(username);
  6. jdbcRs.setPassword(password);
  7. jdbcRs.execute();
  8. // ...
  9. }

在使用方法setCommand指定 SQL 语句,指定JdbcResultSet对象如何连接数据库,然后运行方法execute之前,对象jdbcRs不包含任何数据。

所有参考实现构造器都为 Default JdbcRowSet Objects 部分中列出的属性分配默认值。

使用 RowSet 1.1(它是 Java SE 7 及更高版本的一部分),您可以使用RowSetFactory的实例来创建JdbcRowSet对象。例如,以下代码摘录使用RowSetFactory接口的实例来创建JdbcRowSet对象,jdbcRs

  1. public void createJdbcRowSetWithRowSetFactory(
  2. String username, String password)
  3. throws SQLException {
  4. RowSetFactory myRowSetFactory = null;
  5. JdbcRowSet jdbcRs = null;
  6. ResultSet rs = null;
  7. Statement stmt = null;
  8. try {
  9. myRowSetFactory = RowSetProvider.newFactory();
  10. jdbcRs = myRowSetFactory.createJdbcRowSet();
  11. jdbcRs.setUrl("jdbc:myDriver:myAttribute");
  12. jdbcRs.setUsername(username);
  13. jdbcRs.setPassword(password);
  14. jdbcRs.setCommand("select * from COFFEES");
  15. jdbcRs.execute();
  16. // ...
  17. }
  18. }

以下语句使用默认RowSetFactory实现创建RowSetProvider对象myRowSetFactorycom.sun.rowset.RowSetFactoryImpl

  1. myRowSetFactory = RowSetProvider.newFactory();

或者,如果 JDBC 驱动程序具有自己的RowSetFactory实现,则可以将其指定为newFactory方法的参数。

以下语句创建JdbcRowSet对象jdbcRs并配置其数据库连接属性:

  1. jdbcRs = myRowSetFactory.createJdbcRowSet();
  2. jdbcRs.setUrl("jdbc:myDriver:myAttribute");
  3. jdbcRs.setUsername(username);
  4. jdbcRs.setPassword(password);

RowSetFactory接口包含创建 RowSet 1.1 及更高版本中可用的不同类型RowSet实现的方法:

  • createCachedRowSet
  • createFilteredRowSet
  • createJdbcRowSet
  • createJoinRowSet
  • createWebRowSet

使用默认构造器创建JdbcRowSet对象时,新的JdbcRowSet对象将具有以下属性:

  • typeResultSet.TYPE_SCROLL_INSENSITIVE(有可滚动的光标)
  • concurrencyResultSet.CONCUR_UPDATABLE(可更新)
  • escapeProcessingtrue(驱动程序将执行转义处理;启用转义处理时,驱动程序将扫描任何转义语法并将其转换为特定数据库可识别的代码)
  • maxRows0(行数无限制)
  • maxFieldSize0(列值的字节数没有限制;仅适用于存储BINARYVARBINARYLONGVARBINARYCHARVARCHARLONGVARCHAR的列值)
  • queryTimeout0(没有时间限制执行查询所需的时间)
  • showDeletedfalse(删除的行不可见)
  • transactionIsolationConnection.TRANSACTION_READ_COMMITTED(仅读取已提交的数据)
  • typeMapnull(与RowSet对象使用的Connection对象关联的类型映射为null

从这个列表中你必须记住的主要事情是JdbcRowSet和所有其他RowSet对象是可滚动和可更新的,除非你为这些属性设置不同的值。

默认 JdbcRowSet 对象部分列出了创建新JdbcRowSet对象时默认设置的属性。如果使用默认构造器,则必须先设置一些其他属性,然后才能使用数据填充新的JdbcRowSet对象。

为了获取其数据,JdbcRowSet对象首先需要连接到数据库。以下四个属性包含用于获取与数据库的连接的信息。

  • username:用户提供给数据库的名称,作为获取访问权限的一部分
  • password:用户的数据库密码
  • url:用户想要连接的数据库的 JDBC URL
  • datasourceName:用于检索已使用 JNDI 命名服务注册的DataSource对象的名称

您设置的这些属性中的哪一个取决于您要如何建立连接。首选方法是使用DataSource对象,但使用 JNDI 命名服务注册DataSource对象可能不实用,这通常由系统管理员完成。因此,代码示例都使用DriverManager机制来获取连接,您使用url属性而不是datasourceName属性。

您必须设置的另一个属性是command属性。此属性是确定JdbcRowSet对象将包含哪些数据的查询。例如,以下代码行使用查询设置command属性,该查询生成包含表COFFEES中所有数据的ResultSet对象:

  1. jdbcRs.setCommand("select * from COFFEES");

设置command属性和建立连接所需的属性后,可以通过调用execute方法用数据填充jdbcRs对象。

  1. jdbcRs.execute();

execute方法在后台为您做了很多事情:

  • 它使用您分配给urlusernamepassword属性的值建立与数据库的连接。
  • 它执行您在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对象中的第四行,然后返回到第三行:

  1. jdbcRs.absolute(4);
  2. jdbcRs.previous();

方法previous类似于方法next,因为它可以在while循环中用于按顺序遍历所有行。不同之处在于您必须将光标移动到最后一行之后的位置,previous将光标移向开头。

您更新JdbcRowSet对象中的数据的方式与更新ResultSet对象中的数据的方式相同。

假设咖啡休息所有者想要提高一磅 Espresso 咖啡的价格。如果所有者知道 Espresso 位于jdbcRs对象的第三行,则执行此操作的代码可能如下所示:

  1. jdbcRs.absolute(3);
  2. jdbcRs.updateFloat("PRICE", 10.99f);
  3. jdbcRs.updateRow();

代码将光标移动到第三行,并将列PRICE的值更改为 10.99,然后使用新价格更新数据库。

调用方法updateRow会更新数据库,因为jdbcRs已保持与数据库的连接。对于断开连接的RowSet对象,情况有所不同。

如果 Coffee Break 连锁店的所有者想要将一种或多种咖啡添加到他提供的产品中,那么所有者将需要在每个新咖啡的COFFEES表中添加一行,如下面的代码片段所示。 ] [JdbcRowSetSample]($docs-gettingstarted.html)。请注意,因为jdbcRs对象始终连接到数据库,所以在JdbcRowSet对象中插入行与在ResultSet对象中插入行相同:将光标移动到插入行,使用适当的 updater 方法为每列设置一个值,并调用方法insertRow

  1. jdbcRs.moveToInsertRow();
  2. jdbcRs.updateString("COF_NAME", "HouseBlend");
  3. jdbcRs.updateInt("SUP_ID", 49);
  4. jdbcRs.updateFloat("PRICE", 7.99f);
  5. jdbcRs.updateInt("SALES", 0);
  6. jdbcRs.updateInt("TOTAL", 0);
  7. jdbcRs.insertRow();
  8. jdbcRs.moveToInsertRow();
  9. jdbcRs.updateString("COF_NAME", "HouseDecaf");
  10. jdbcRs.updateInt("SUP_ID", 49);
  11. jdbcRs.updateFloat("PRICE", 8.99f);
  12. jdbcRs.updateInt("SALES", 0);
  13. jdbcRs.updateInt("TOTAL", 0);
  14. jdbcRs.insertRow();

当您调用方法insertRow时,新行将插入jdbcRs对象并插入到数据库中。前面的代码片段经过两次这个过程,因此在jdbcRs对象和数据库中插入了两个新行。

与更新数据和插入新行一样,删除行对于JdbcRowSet对象与ResultSet对象相同。店主想要停止销售法国烤无咖啡因咖啡,这是jdbcRs对象的最后一行。在以下代码行中,第一行将光标移动到最后一行,第二行删除jdbcRs对象和数据库中的最后一行:

  1. jdbcRs.last();
  2. jdbcRs.deleteRow();

样例[JdbcRowSetSample]($docs-gettingstarted.html)执行以下操作:

  • 创建一个新的JdbcRowSet对象,该对象使用ResultSet对象初始化,该对象是由执行检索COFFEES表中的所有行的查询生成的
  • 将光标移动到COFFEES表的第三行并更新该行中的PRICE
  • 插入两个新行,一个用于HouseBlend,另一个用于HouseDecaf
  • 将光标移动到最后一行并删除它