支持的数据类型
本版 JDBC 增加了一些新的数据类型,对其他的一些数据类型,则提供了更好的支持 . 笔者为 XML 被正式支持感到欣喜 , 本版中产生了一个新的接口 : SQLXML . 在笔者看来这个接口值得单独开一个章节为其讨论:
SQLXML 与 XML 的支持
SQLXML 是 SQL 中 XML 数据类型在 Java 中的表示, XML 是 SQL 中用于表示表中 XML 数据的内建数据类型 . 在默认的情况下, JDBC 驱动将 SQLXML 指针指向 XML 数据而不是数据本身 . SQLXML 对象在其被创建的事务中是稳定的 .
在下面的 Example3 类中 , 笔者将说明如何在当前连接中应用 SQLXML 并更新表数据 .
public class Example3 { public static void main(String[] args) { ... con = ds.getConnection(); SQLXML sx= con.createSQLXML(); sx.setString("Math is Fun"); String psx ="insert into "+tableName+ " ( id, textbook) values(?,?) "; PreparedStatement pstmt = con.prepareStatement(psx); pstmt.setString(1,"1000"); pstmt.setSQLXML(2,sx); pstmt.executeUpdate(); ... } }
这个例子说明了您所能应用的最简单的情况 . 如果我们继续深入研究,事情就会变得有趣得多了 . 但在我们深入讨论之前 , 让我来告诉您运行 Example3.java . 的结果。 非常不幸 , 我无法获取到 SQLXML 对象,并得到了以下让人失望的输出:
java.sql.SQLFeatureNotSupportedException: Feature not
implemented: no details.
at org.apache.derby.impl.jdbc.SQLExceptionFactory40.
getSQLException(Unknown Source)
... ... ... ...
at ex.Example3.main(Example3.java:62)
看来 Apache Derby 并没有提供从 Connection 中获取 SQLXML 对象的方法 . 但至少您可以看到笔者正试图在类 Example3 中实现的东西 : 我想插入一行新的数据: id 列值为 1000 textbook 列 (S QLXML 类型 ) 插入 Math is Fun .
笔者用如下代码段结束关于 SQLXML 的讨论,这段代码从数据库中读取 XML 值并将其转化为 Document 对象 .
SQLXML sqlxml = rs.getSQLXML(column);
InputStream binaryStream = sqlxml.getBinaryStream();
DocumentBuilder parser =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = parser.parse(binaryStream);
可以把一个列的值直接转化为 XML 文档不是一件令人兴奋的事情吗 ? 我觉得这个特性非常好 .
ROWID 数据类型
SQL ROWID 唯一标识了数据表中的一行,并是访问该行的最快的方法, 本版增加了 RowId 接口以提供对 ROWID SQL 数据类型在 Java 类中的支持 .
对大对象类型支持的增强
JDBC 版本 2 提供了对大的 SQL 对象如: CLOB , BLOB , ARRAY 的支持 , 及用于添加相关接口的 Struct: Clob , Blob , Array , and Struct . 在本版的 JDBC 中增加了很多对这些对象访问的新方法 . 笔者将在 API 变化一节中进行详细论述 .
支持 National Character Set ( NCS ) 转化
SQL:2003 提出了如下 SQL 数据类型的支持: NCHAR , NVARCHAR , LONGNVARCHAR , 及 NCLOB . 其功用和 CHAR , VARCHAR , LONGVARCHAR , 及 CLOB 类似 ,其区别仅是,这些类型的文本是用 NCS 编码的。 如果需要大量的字符处理,您可能更倾向于 NCS 数据类型而非普通的数据类型。本版 JDBC 提供了增强对 NCS 支持的 API.
- 在 PreparedStatement , CallableStatement , 及 ResultSet 接口中增加了一些 setter 和 updater 方法以支持 NCS 转化 . 比如方法 setNString , setNCharacterStream , 及 setNClob 等等 .
- 在 SQLInput and SQLOutput 接口中增加了读写方法以支持 t NClob 和 NString 对象 .
API 变化
JDBC 4.0 最大的变化来自于 API, 笔者在本小节对其做简单介绍 .
Array
Array 接口增加了一个 free 方法来释放 array 对象及其持有的资源 .
Connection 和 PooledConnection
Connection 接口现在提供一系列创建大对象的方法如 createClob , createBlob 等等 . 此外还有 getter 和 setter 对客户端信息的重载方法 , 及验证当前连接正确性的方法 .
PooledConnection 接口当前提供 addStatementEventListener 和 removeStatementEventListener 两个方法来注册和注销 StatementEventListener 接口 , 这个接口是在本版 JDBC 中新引入的 . 这个接口的一个实例将获取到 S tatement 池中 PreparedStatement s 的变化 . 比如,在注册以后 , 当驱动调用 statementClosed 方法时,所有 StatementEventListener 将获得 statement 已关闭的通知 .
DatabaseMetaData
不同的关系数据库往往支持不同的特性 , 并通过不同的方法来实现这些特性 , 并可能会是用不同的数据类型 . 这将会导致移植性的问题,因为根据实现的不同,无法保证代码在所有关系数据库上都能正确执行 . 这样的问题在一定程度上可以通过这个接口所获得的信息来解决 . 比如,如果您在写一个通过传入 SQL 语句来建立表的代码 . 您可能想知道在 CREATE TABLE 语句中有哪些数据类型是可用的,此时可以调用该接口中的 getTypeInfo 方法 .
本版 JDBC 增加了一些获取信息的方法 . 在 Example4 中 , 我将通过一段代码展示如何获得满足某种模式的数据库结构的列表。 .
con = ds.getConnection();
DatabaseMetaData dmd = con.getMetaData();
rs=dmd.getSchemas("TABLE_CAT", "SYS%");
//iterate over the rs and print to console
首先通过调用 dmd.getCatalogs 并遍历结果集 , 得到了唯一的一个值: TABLE_CAT . 接着通过调用 rs=dmd.getSchemas("TABLE_CAT", "SYS%") 得到以 SYS 开头的数据库和表结构 . 以下是笔者得到的结果 :
SYS
SYSCAT
SYSCS_DIAG
SYSCS_UTIL
SYSFUN
SYSIBM
SYSPROC
SYSSTAT
Scalar 函数支持
一个 scalar 函数操作预定义的输入数据集合并返回结果 . 比如: scalar 函数调用 ABS(number) 返回 number 的绝对值 . 这些 scalar 函数可以作为 SQL 字符串的一部分来使用 . 本版 JDBC 要求当所依赖的关系数据库支持以下功能时: CHAR_LENGTH , CHARACTER_LENGTH , CURRENT_DATE , CURRENT_TIME , CURRENT_TIMESTAMP , EXTRACT , OCTET_LENGTH , 和 POSITION ,驱动必须实现这些功能。
Statement , PreparedStatement , 和 CallableStatement
Statement 接口当前提供 isClosed 方法来判断 statement 是否已关闭 , setPoolable 用来设置是否可以被池化 , 用 isPoolable 来检测当前的池化状态。
PreparedStatement 及 CallableStatement 接口现在提供了更多插入大对象的方法 , 通过使用 InputStream 及 Reader 等 .
Wrapper
这个版本的 API 增加了一个新的 Wrapper 接口, 来提供一种访问资源的实例的方法 , 这可能是基于架构的考虑 . Wrapper 模式 , 被许多的 JDBC 驱动实现应用以提供 JDBC API 之外的依赖于具体数据源的应用 . 这个接口的主要目的是用来提供供应商相关的功能。您可以通过调用 unwrap 方法来获取到数据库连接的接口实现的实例 . 因为这是一个重量级的操作 , 在使用前,应该先调用 isWrapperFor 方法来检测是否当前实例是某种实现的一个间接或直接的 Wapper
能够给出一个程序例子当然是最好的,但是 Apache Derby 参考手册 l 指出 : "JDBC 4.0 引入了 wrapped JDBC 对象的概念 ... 对于 Derby 来说 , 这对 Derby 来说是没有意义的,因为 Derby 并不做规范之外的扩展 ." 因此看来这种尝试也就变得无甚必要了 !
结论
我们已经分为 4 类讨论了 JDBC 4.0 所做的一些改进和新的特性,这些新特性增加了编程易用性,提高了生产率 . 尽管 API 规范已经推出几个月了 , 到笔者截稿时,主流的数据库厂商都没有提供本版的 JDBC 驱动 . 当更多的供应商开始支持 JDBC 4.0 时 — 当然也包括您所中意的那个 — 您就可以享受 JDBC4.0 所提供的这些易用的功能了 .
最后,我认为有一个各大数据库厂商的支持的 JDBC 版本的列表是必要的 . Sun Developer Network (SDN) 上有一个 JDBC Data Access API ( http://developers.sun.com/product/jdbc/drivers ) 页提供了一份更新不太及时的列表 .