目录 | 上一页 | 下一页 JDBCTM 指南:入门


8 新的 SQL 类型

以下两章讨论了 JDBC 2.0 API 的附加部分,它们可以使 Java 应用程序能访问新的 SQL 数据类型,例如二进制大型对象和结构化类型。不支持新的 SQL 类型的 JDBC 驱动程序不需要实现这两章中所述的方法和接口。

8.1  SQL 类型的分类

通常将 ANSI/ISO SQL 标准的下一个版本称为 SQL3。详细说明该标准的工作文档称为 SQL3 草案。该草案现在正处于标准化过程的阶段,不会有较大的增加或变化 — 只作较小的变化和修改。SQL3 中所含的数据类型的基本种类不会在标准化过程的最后阶段发生变化。

JDBC 2.0 API 融入了新 SQL3 类型的模型,其中只包括了在 Java 应用程序和数据库之间交换数据所需的属性。在本草案成为正式标准之前,即使改变新 SQL3 类型的语法和服务器端语义的部分细节,也不应该影响 JDBC 2.0 API。

SQL3 草案定义了以下数据类型:

REF 值仍表示驻留在数据库中的结构化类型的实例。LOCATOR 只存在于客户机环境下, 而且是指向驻留在数据库服务器上的数据的瞬态逻辑指针。定位符通常用来引用因太大而不能在客户机上实现的数据,例如图像和音频。在 SQL 级中所定义的操作符可以检索定位符所表示的随机存取数据块。

本章的其余部分讨论了 JDBC 2.0 API 所提供的缺省机制,可用来访问以上所提及的每种新 SQL 类型。JDBC 2.0 API 还提供了一种方法,可以自定义从 SQL distinct 和结构化类型到 Java 类的映射方式。在第 9 章中讨论了这种机制。

8.2 Blob 和 clob

8.2.1 检索 blob 和 clob

对二进制大型对象 (blob) 和字符大型对象 (clob) 数据类型的处理类似于现有的内嵌 JDBC 类型。通过调用出现在 ResultSetCallableStatement 接口上的 getBlob()getClob() 方法可以检索这些类型的值。例如,

Blob blob = rs.getBlob(1);
Clob clob = rs.getClob(2);


从结果集的第一列检索 blob 值而从第二列检索 clob 值。Blob 接口所含的操作可以返回 blob 的长度、blob 中特定的一段字节等。Clob 接口所含的相应操作是基于字符的。详细信息,参见附带的 API 文档。

JDBC 应用程序并不直接处理在 SQL 中定义的 LOCATOR(blob) 和 LOCATOR(clob) 类型。缺省情况下,JDBC 驱动程序应该使用适当的 locator(定位符)类型来实现 BlobClob 接口。同样,在缺省情况下,BlobClob 对象只是在创建它们的事务处理过程中保持有效。JDBC 驱动程序可能允许改变这些缺省值。例如,可以将 BlobClob 对象的寿命更改为在会话作用域内。然而,JDBC 2.0 API 并没有规定具体的操作步骤。

8.2.2 存储 blob 和 clob

通过分别调用 setBlob()setClob() 方法,用户即可象对待其它 JDBC 数据类型一样将 BlobClob 值作为输入参数传给 PreparedStatement 对象。可以使用 setBinaryStream()setObject() 方法来将流值作为 blob 输入。可以使用 setAsciiStream()setUnicodeStream()setObject() 方法来将流值作为 clob 输入。

8.2.3 元数据增加部分

java.sql.Types 中增加了两种新的类型代码,即 BLOBCLOB 。当 JDBC 支持这两种数据类型时,由诸如 DatabaseMetaData.getTypeInfo()DatabaseMetaData.getColumns() 的方法返回这些值。

8.3 数组

8.3.1 检索数组

通过调用 ResultSet CallableStatement 接口的 getArray() 方法可以检索 SQL 类型数组的数据。例如,

Array a = rs.getArray(1);


从结果集的第一列检索 Array 值。缺省情况下,JDBC 驱动程序应该在内部使用 SQL LOCATOR(array) 来实现 Array 接口。同样,缺省情况下,Array 对象只是在创建它的事务处理过程中保持有效。对于 BlobClob 类型来说,可以改变这些缺省值,但是 JDBC 2.0 API 没有规定具体的操作步骤。

Array 接口提供了几种方法可以将数组内容作为已实现的 Java 数组或 ResultSet 对象返回给客户机。这些方法分别为 getArray() getResultSet()。详细信息,参见单独的 API 文档。

8.3.2 存储数组

可以调用 PreparedStatement.setArray() 方法将 Array 值作为输入参数传递给预先准备好的语句。通过调用 PreparedSatement.setObject() 可以将 Java 编程语言数组作为输入参数进行传递。

8.3.3 元数据增加部分

java.sql.Types 中增加了新的类型代码,即 ARRAY。当 JDBC 支持 Array 数据类型时,由诸如 DatabaseMetaData.getTypeInfo()DatabaseMetaData.getColumns() 的方法返回该值。

8.4 Ref

8.4.1 检索 ref

通过调用 ResultSetCallableStatement 接口的 getRef() 方法可以检索 SQL 引用。例如,

Ref ref = rs.getRef(1);


从创建它的结果集的第一列检索 Ref 值。缺省情况下,检索 Ref 值的操作并不会实现 Ref 所引用的数据。同样,在缺省情况下,当会话或连接处于打开状态时,Ref 值将保持有效状态。可以覆盖这些缺省值,但是 JDBC 2.0 API 也没有规定具体的操作步骤。

Ref 接口没有提供取消引用的方法。而是可以将 Ref 作为输入参数传给适当的 SQL 语句,再由该语句取回它所引用的对象。详细信息,参见单独的 JDBC API 文档。

8.4.2 存储 ref

可以调用 PreparedStatement.setRef() 方法来将 Ref 作为输入参数传递到预先准备好的语句。

8.4.3 元数据增加部分

java.sql.Types 中增加了新的类型代码,即 REF。当 JDBC 支持Ref 数据类型时,由诸如 DatabaseMetaData.getTypeInfo()DatabaseMetaData.getColumns() 的方法返回该值。

8.5 Distinct 类型

8.5.1 检索 distinct 类型

缺省情况下,通过调用 distinct 类型相应的基本类型的 getXXX() 方法,可以检索 SQL 类型 DISTINCT 的数据。例如,假设给出以下类型声明:

CREATE TYPE MONEY AS NUMERIC(10,2)

可以采用以下方法来检索 MONEY 类型的值:

java.math.BigDecimal bd = rs.getBigDecimal(1);


这是因为 JDBC 已将基本 SQL NUMERIC 类型映射到 java.math.BigDecimal 类型。

8.5.2 保存 distinct 类型

可以采用 SQL DISTINCT 类型相应的基本类型的 PreparedStatement.setXXX() 方法来将该 distinct 类型的输入参数传给预先准备好的语句。例如,如果给出以上的 MONEY 类型的定义,则可以使用 PreparedStatement.setBigDecimal()

8.5.3 元数据增加部分

java.sql.Types 中增加了新的类型代码,即 DISTINCT。当 JDBC 支持这种数据类型时,由诸如 DatabaseMetaData.getTypeInfo()DatabaseMetaData.getColumns() 的方法返回该值。

在架构表定义中使用 SQL DISTINCT 类型之前,必须将其类型定义为特定数据库架构的一部分。通过调用 DatabaseMetaData.getUDTs() 方法可以检索特定于架构的自定义类型(DISTINCT 类型是其中的一种)的有关信息。例如,

int[] types = {Types.DISTINCT};
ResultSet rs = dmd.getUDTs("catalog-name", "schema-name",
	"%", types);

将返回在 catalog- name.schema-name 架构中定义的所有 SQL DISTINCT 类型的描述。如果驱动程序不支持 UDT 或者没有找到匹配的 UDT,则返回空结果集。

每种类型描述都有以下各列:

TYPE_CAT String => 类型的目录(可以为空)
TYPE_SCHEM String => 类型的架构(可以为空)
TYPE_NAME String => 数据库类型名称
JAVA_CLASS String => Java 类或接口名称
DATA_TYPE short => java.sql.Types 中所定义的值,例如 DISTINCT
REMARKS String => 对类型的解释性注释

以上的大多数列应该是无需加以解释的。上例中, TYPE_NAME 是赋予 DISTINCT 类型 (MONEY) 的 SQL 类型名。CREATE TABLE 语句指定这种类型的列时也使用该名称。

DATA_TYPETypes.DISTINCT 时,JAVA_CLASS 列就包含全限定的 Java 类名。如果在这种 DISTINCT 类型的列上调用 getObject(),则将创建本类的实例。例如,在以上的 MONEY 情况下,JAVA_CLASS 将采用缺省设置 java.math.BigDecimal。JDBC 2.0 API 并不禁止驱动程序返回名为 JAVA_CLASS 的类的子类型。当使用 JAVA_CLASS 时, JAVA_CLASS 的值反映自定义类型映射。详细信息,参见第 9 章。

8.6 构化类型

8.6.1 检索结构化类型

调用方法 getObject() 总能检索 SQL 结构化类型的数值。缺省情况下,getObject() 为结构化类型返回 Struct 类型的值。例如,

Struct struct = (Struct)rs.getObject(1);

从结果集 rs 的当前行的第一列检索 Struct 值。Struct 接口所含的方法可以将结构化类型的属性当作 java.lang.Object 值的数组来检索。缺省情况下,JDBC 驱动程序在将指向 Struct 的引用返回给应用程序之前,应该先实现 Struct 的内容。同样,缺省情况下只要 Java 应用程序保留了指向 Struct 对象的引用,就认为 Struct 对象是有效的。JDBC 驱动程序可能会允许改变这些缺省值 — 例如,允许使用 SQL LOCATOR — 但是 JDBC 2.0 API 并没有规定具体的操作步骤。

8.6.2 存储结构化类型

可以调用 PreparedStatement.setObject() 方法来将 Struct 作为输入参数传递给预先准备好的语句。

8.6.3 元数据增加部分

java.sql.Types 中增加了一种新的类型代码,即 STRUCT。当 JDBC 驱动程序支持结构化数据类型时,将通过诸如 DatabaseMetaData.getTypeInfo()DatabaseMetaData.getColumns() 的方法返回该值。

在架构表定义中使用结构化的 SQL 类型之前,必须将结构化的 SQL 类型定义为特定数据库架构的一部分。通过调用 DatabaseMetaData.getUDTs() 方法可以检索特定于架构的自定义类型(STRUCT 类型是其中的一种)的有关信息。例如,

int[] types = {Types.STRUCT};
ResultSet rs = dmd.getUDTs("catalog-name", "schema-name",
	"%", types);

返回在 catalog- name.schema-name 架构中定义的所有结构化 SQL 类型的描述。如果驱动程序不支持 UDT 或者找不到匹配的 UDT,则返回空结果集。有关 getUDTs() 所返回结果集的描述,参见 8.5.3 一节。

getUDTs() 所返回的 DATA_TYPETypes.STRUCT 时,JAVA_CLASS 列就包含 Java 类的全限定的 Java 类名。在这种 STRUCT 类型的列上调用 getObject() 时,由 JDBC 驱动程序生成该类的实例。这样,JAVA_CLASS 对于结构化类型会采用缺省设置 java.sql.Struct 。第 9 章讨论 Java 应用程序如何修改这个缺省值。在这里我们只指出一点:JDBC 2.0 API 不禁止驱动程序返回名为 JAVA_CLASS 的类的子类型。



目录 | 上一页 | 下一页


jdbc@eng.sun.comjdbc-business@eng.sun.com

版权所有 © 1996, 1997 Sun Microsystems, Inc. 保留所有权利