OceanBase LONG 和 LONG RAW 数据类型
当查询选择一个或多个 LONG
或 LONG RAW
列时,OceanBase Connector/J 将这些列以流模式传输到客户端。
在流模式下,OceanBase Connector/J 一般不会从网络读取 LONG
或 LONG RAW
列的数据。在使用代码调用 getXXX
方法读取列数据之前,列数据将保留在网络通信通道中。除了读取列数据外,任何连接使用都会将列数据从通道中丢弃。虽然流模式可以有效利用内存并最大程度地减少往返通信,但它会干扰其他数据库操作。
要访问 LONG
列中的数据,您可以将该列作为 Java InputStream
对象,并使用 InputStream
对象的 read
方法获取。也可以将数据作为 String
或 byte
数组,通过执行流传输获取。
三种流类型都可以获取 LONG
和 LONG RAW
数据。驱动程序将根据数据库和驱动程序的字符集进行执行转换。
注意
不要创建带有LONG
列的表。可以改用大对象(LOB
)列:CLOB
、NCLOB
和BLOB
。因为LOB
列的使用限制远少于LONG
列,所以建议将现有的LONG
列转换为LOB
列。
LONG RAW 数据转换
调用 getBinaryStream
返回 RAW
数据。调用 getAsciiStream
会将 RAW
数据转换为十六进制并返回相应的 ASCII。调用 getUnicodeStream
会将 RAW
数据转换为十六进制并返回
Unicode 字符。
LONG 数据转换
使用 getAsciiStream
获取 LONG
数据时,驱动程序会假定数据库中的基础数据使用 US7ASCII
或 WE8ISO8859P1
字符集。如果假设为真,则驱动程序将返回与 ASCII 字符相对应的字节。如果数据库未使用 US7ASCII
或 WE8ISO8859P1
字符集,则调用 getAsciiStream
将返回无意义的信息。
使用 getUnicodeStream
获取 LONG
数据时,将获得 UTF-16 编码的 Unicode 字符流。
使用 getBinaryStream
获取 LONG
数据时,如果数据库字符集不是 US7ASCII
或 WE8ISO8859P1
,则调用 getBinaryStream
将返回 UTF-8。如果服务器端字符集是 US7ASCII
或 WE8ISO8859P1
,则调用将返回 US7ASCII
字节流。
注意
将LONG
或LONG RAW
列作为流进行接收时,需要特别注意在数据库中检索的列的顺序。LONG
和LONG RAW
数据转换的详细信息如下表所示。
数据类型 |
BinaryStream |
AsciiStream |
UnicodeStream |
---|---|---|---|
LONG |
字节表示 Unicode UTF-8 中的字符。如果数据库字符集为 |
字节表示 ISO-Latin-1( |
字节代表 Unicode UTF-16 编码的字符。 |
LONG RAW |
数据不变数据。 |
十六进制字节的 ASCII 表示形式。 |
十六进制字节的 Unicode 表示形式。 |
示例
getXXXStream
方法的功能之一是能够以增量方式获取数据,而 getBytes
在一次调用中就获取所有数据。以下是获取二进制数据流的示例。
示例 1:使用 getBinaryStream 方法获取 LONG RAW 数据
-
创建表
stream01
,存储与名称SAMPLE
相关的LONG RAW
数据列。CREATE TABLE stream01 (name VARCHAR2 (50), giftype LONG RAW); INSERT INTO stream01 VALUES ('SAMPLE', '1234567890123');
-
将
LONG RAW
列中的数据写入名为sample.gif
的文件中。ResultSet rs = st.executeQuery ("select giftype from stream01 where NAME='SAMPLE'");
-
使用
getBinaryStream
方法获取LONG RAW
数据。// 获取第一行 if (rs.next()) { // 以流形式获取 GIF 数据 InputStream gif_type = rs.getBinaryStream (1); try { FileOutputStream file = null; file = new FileOutputStream ("sample.gif"); int chunk; while ((chunk = gif_type.read()) != -1) file.write(chunk); } catch (Exception e) { String err = e.toString(); System.out.println(err); } finally { if file != null() file.close(); } }
上述示例中,调用 getBinaryStream
返回的 InputStream
对象直接从数据库连接中读取数据。
示例 2:使用 getBytes 方法获取 LONG RAW 数据
本示例使用 getBytes
获取 giftype
列的内容,驱动程序将在一次调用中获取所有数据,并将其存储在字节数组中。
ResultSet rs2 = st.executeQuery
("select giftype from streame01 where NAME='SAMPLE'");
// 获取第一行
if (rs2.next())
{
// 以流形式获取 GIF 数据
byte[] bytes = rs2.getBytes(1);
try
{
FileOutputStream file = null;
file = new FileOutputStream ("sample2.gif");
file.write(bytes);
}
catch (Exception e)
{
String err = e.toString();
System.out.println(err);
}
finally
{
if file != null()
file.close();
}
}
因为 LONG RAW
列最多可以包含 2 GB 的数据,所以与 getBinaryStream
示例相比,getBytes
示例可以使用更多的内存。如果不知道 LONG
或 LONG RAW
列中数据的最大大小,请使用流。
说明
- OceanBase Connector/J 可以自动流传输任何
LONG
和LONG RAW
列。但在某些情况下,您可能希望避免数据流传输。例如,当LONG
列很小时,这种情况可能就要避免递增式返回数据,而是采用一次调用就返回数据。- 为避免流传输,请使用
defineColumnType
方法重新定义LONG
列的类型。例如,可以将LONG
或LONG RAW
列重新定义为VARCHAR
或VARBINARY
类型,则驱动程序将不会自动流传输数据。- 如果使用
defineColumnType
重新定义列类型,则必须在查询中声明列的类型。否则,executeQuery
将执行失败。另外,必须将Statement
对象转换为oceanbase.jdbc.oceanbaseStatement
。