试图从 'CHAR () FOR BIT DATA' 类型的数据值中获取 'java.sql.Blob' 类型的数据值

An attempt was made to get a data value of type 'java.sql.Blob' from a data value of type 'CHAR () FOR BIT DATA'

我正在尝试以通用方式从 Derby 数据库读取数据,我想将 UUID 检索为字节数组 16。通常对于二进制类型,我可以使用 Blob 并将其映射到字节数组。但是在 Derby 中,我得到了这个异常:'试图从 'CHAR () FOR BIT DATA' 类型的数据值中获取 'java.sql.Blob' 类型的数据值。'

架构

CREATE TABLE Contacts(  ID CHAR(16) FOR BIT DATA NOT NULL PRIMARY KEY ... etc

这给了我 java.sql.Types -2 (BINARY)

当我使用 rs.getBlob 时失败:

 byte[] buffer = new byte[1024];
    Blob blob = rs.getBlob(column);
    try (InputStream in = blob.getBinaryStream()) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) blob.length());
        for (int len; (len = in.read(buffer)) != -1; ) {
            bos.write(buffer, 0, len);
        }
        value = bos.toByteArray();
    }

但如果我使用它确实有效:

value = rs.getBytes(column)

现在我可以只使用 rs.getBytes 除非以后我还需要来自 Derby 的“真正的”Blob。我怎么能分辨出区别?还是 Derby 总是使用 getBytes?

java.sql.Blob 用于 JDBC 类型 BINARY 从严格的 JDBC API 解释来看是错误的,无论您使用哪个驱动程序。使用 getBytes 始终是这种类型的合适方法(getBinaryStream 也应该有效)。另见 JDBC 4.3 specification,附录 B,特别是 table B-3,它将 JDBC 类型 BINARY 的默认 Java 类型定义为 byte[]和 B-5,它只定义了从 java.sql.Blob 到 JDBC 类型 BLOB 的映射,而 B-6 只定义了对 getBlob 的列的支持 JDBC 输入 BLOB.

明确地说,JDBC 类型 BINARY - 通常 - 映射 to/from SQL 类型 BINARY(Derby 的等价物称为 CHAR FOR BIT DATA), 为定长字节string/array类型。而 SQL(和 JDBC)BLOB 是一种通过所谓的定位器对象保存可变长度(通常是无限长度(或至少非常大))的二进制数据的类型。 BLOB 数据通常存储在行外(该行仅包含实际数据的指针或 id),而 BINARY(和 VARBINARY)通常存储在行内。 java.sql.Blob 是该定位器对象的 Java 表示,提供间接访问 blob 的行外数据。

然而,一些驱动程序更为宽松,要么是为了与驱动程序的早期版本向后兼容,要么是为了最大程度的可移植性(例如,桥接不同数据库系统之间的实现差异)。例如,某些驱动程序可能会将其 (SQL) BLOB 类型定义为 JDBC LONGVARBINARY(支持 getBytesgetBinaryStream),但是然后还可以定义对 getBlob 的支持,以防用户假设 “我使用 SQL BLOB,所以我应该使用 getBlob.

所以,简而言之,如果该列被标识为 JDBC 类型 BINARY,则使用 getBytes(或 getInputStream,但是如果您想获得UUID,始终为 16 个字节,然后使用 getBytes 更有意义)。如果该行被标识为 JDBC 类型 BLOB,则使用 getBlob(尽管某些驱动程序可能也支持 getBytesgetInputStream,但在 JDBC).