试图从 '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
(支持 getBytes
和 getBinaryStream
),但是然后还可以定义对 getBlob
的支持,以防用户假设 “我使用 SQL BLOB
,所以我应该使用 getBlob
”.
所以,简而言之,如果该列被标识为 JDBC 类型 BINARY
,则使用 getBytes
(或 getInputStream
,但是如果您想获得UUID,始终为 16 个字节,然后使用 getBytes
更有意义)。如果该行被标识为 JDBC 类型 BLOB
,则使用 getBlob
(尽管某些驱动程序可能也支持 getBytes
和 getInputStream
,但在 JDBC).
我正在尝试以通用方式从 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
(支持 getBytes
和 getBinaryStream
),但是然后还可以定义对 getBlob
的支持,以防用户假设 “我使用 SQL BLOB
,所以我应该使用 getBlob
”.
所以,简而言之,如果该列被标识为 JDBC 类型 BINARY
,则使用 getBytes
(或 getInputStream
,但是如果您想获得UUID,始终为 16 个字节,然后使用 getBytes
更有意义)。如果该行被标识为 JDBC 类型 BLOB
,则使用 getBlob
(尽管某些驱动程序可能也支持 getBytes
和 getInputStream
,但在 JDBC).