【问题标题】:An attempt was made to get a data value of type 'java.sql.Blob' from a data value of type 'CHAR () FOR BIT DATA'尝试从“CHAR () FOR BIT DATA”类型的数据值中获取“java.sql.Blob”类型的数据值
【发布时间】:2021-05-11 11:50:22
【问题描述】:

我正在尝试以通用方式从 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?

【问题讨论】:

  • CHAR FOR BIT DATABLOB 不同。它们是两种不同的数据类型。两者都与CLOB 不同。使用 JDBC BLOB API 访问 BLOBCLOB 列,而不是访问其他数据类型的列。这是你的问题吗?
  • @BryanPendleton 没关系。只要我能够从 jdbc 元数据中分辨出来。我可以。

标签: java jdbc derby


【解决方案1】:

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

需要明确的是,JDBC 类型 BINARY - 通常 - 映射到/来自 SQL 类型 BINARY(Derby 的等价物称为 CHAR FOR BIT DATA),这是一个固定长度的字节字符串/数组类型。而 SQL(和 JDBC)BLOB 是一种通过所谓的定位器对象保存可变长度(通常是无限长度(或至少非常大))的二进制数据的类型。 BLOB 数据通常存储在行外(行仅包含实际数据的指针或 id),而 BINARY(和 VARBINARY)通常内联存储。 java.sql.Blob 是该定位器对象的 Java 表示形式,提供了访问 blob 行外数据的间接途径。

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

因此,简而言之,如果该列被标识为 JDBC 类型 BINARY,则使用 getBytes(或 getInputStream,但是如果您想获得一个始终为 16 字节的 UUID,则使用 @987654350 @ 更有意义)。如果该行被标识为 JDBC 类型BLOB,则使用getBlob(尽管某些驱动程序可能还支持getBytesgetInputStream,这在JDBC 中没有指定)。

【讨论】:

  • 谢谢。是的,我意识到有一个用于 Blob 和各种二进制类型的 java.sql.Types。
  • @sproketboy 是的,JDBC 类型BINARY 并不表示“任何二进制数据类型”,它只涵盖了SQL 标准中称为BINARY 的定长二进制数据类型(还有@ 987654357@ 和 LONGVARBINARY(尽管 SQL 标准没有指定该类型),当然还有 BLOB)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 2021-08-27
  • 1970-01-01
  • 2012-01-27
  • 2020-09-14
相关资源
最近更新 更多