6.1.5 RowSet实现提供者

javax. sql.RowSet接口是JDBC 2.0引入的表格式数据的抽象表示形式。RowSet接口继承自ResultSet接口,并在ResultSet接口的基础上添加了属性设置和变化通知相关的功能。RowSet接口是符合JavaBeans组件规范的,可以与其他JavaBeans组件协同使用。RowSet接口的使用者并不需要显式地管理数据库连接,只需要把数据库相关的连接信息以属性的方式设置到RowSet接口的实现对象中即可。RowSet接口的实现会负责处理数据库连接的相关工作。RowSet接口有5个不同的子接口,每个子接口实现所适应的场景不同。每个子接口对应的具体实现类也有不少,分别来自不同的提供者。在Java 7之前并没有一个规范的方式来管理RowSet接口的实现对象的创建,开发人员需要直接根据实现类的类名来创建新的RowSet接口的实现对象。这种直接依赖具体类而不是接口的做法,不利于代码的移植和维护。

Java 7对RowSet接口的实现对象的创建做了更新,采用了Java标准的服务提供者接口(Service Provider Interface, SPI)机制。使用者通过工厂方法来创建具体的RowSet接口的实现对象,而工厂对象本身由RowSet实现的提供者注册到Java平台上。具体的工厂对象的查找和创建是由javax.sql.rowset.RowSetProvider类的静态方法来完成的,具体的工厂对象则实现javax.sql.rowset.RowSetFactory接口。RowSetFactory接口提供了5种不同RowSet接口实现的创建方法。代码清单6-4给出了使用javax.sql.rowset.JdbcRowSet实现的示例,从中可以看到RowSet接口的基本用法,数据库连接字符串和SQL语句都是以属性的方式来进行设置的。

代码清单6-4 使用工厂方法创建RowSet接口的实现对象的示例


public void useRowSet()throws SQLException{

RowSetFactory rsFactory=RowSetProvider.newFactory();

try(JdbcRowSet jrs=rsFactory.createJdbcRowSet()){

jrs.setUrl("jdbc:derby://localhost/java7book");

jrs.setCommand("SELECT*FROM book");

jrs.execute();

jrs.absolute(1);

jrs.updateString("name","New book");

jrs.updateRow();

}

}


除了上面介绍的几个比较重要的更新之外,JDBC 4.1还有一些比较小的更新。这些小更新包括:在使用ResultSet中的getObject方法时,可以直接把结果类型的Java类作为参数传递进去,而不需要在调用之后再进行强制类型转换。比如,之前的调用方式是“(String)rs.getObject(1)”,新的调用方式是“rs.getObject(1,String.class)”;表示数据库中元数据的java.sql.DatabaseMetaData接口中新增了getPseudoColumns方法来获取数据库表中包含的伪列(pseudo column)和隐藏列(hidden column)的元数据。伪列指的是不在数据库表结构中定义但可以在查询中获取的列。不同数据库实现所支持的伪列是不同的,比如Oracle数据库允许在查询中使用伪列“ROWNUM”来获取当前行的行号,类似的伪列还有获取当前日期和时间戳的“SYSDATE”和“SYSTIMESTAMP”。隐藏列通常用来保存一些与数据库表相关的内部信息。getPseudoColumns方法的返回值是ResultSet接口的实现对象,其中的每一行都包含了查找到的伪列和隐藏列的名称、数据类型、大小等信息。如果通过Statement接口的setQueryTimeout方法设置了数据库查询的超时等待时间,那么当操作超时的时候,会抛出更加具体的java.sql.SQLTimeoutException异常,而不是通用的SQLException异常。

在使用JDBC 4.1时,需要检测所增加的新特性是否已经被关系数据库实现支持。不同的关系数据库实现在对JDBC规范的支持上可能有所不同。在使用JDBC 4.1的新特性之前,先查看一下所使用的数据库和驱动的相关信息,以确定对JDBC 4.1规范的支持程度。