6. JDBC 大对象数据处理
KingbaseES JDBC 中提供了两个接口用于处理大对象数据:java.sql.Blob 和 java.sql.Clob。oracle 兼容模式下数据库提供了两种类型来存储数据,接口提供的两个类分别对应处理这两种数据类型,故两个类的接口均已实现。但在PG兼容模式下数据库对大对象统一存储,且驱动的 Clob 的类只实现了部分获取数据的接口,设置数据的接口均未实现,故 Clob 接口只能进行数据的接收,如果要更新大对象数据只能使用 Blob 的接口。Clob 接口在两种兼容情况下的具体实现情况可参照 JDBC Clob API 。
6.1. 大对象数据的读取
同检索其他数据类型一样,用同样的方法可以从一个结果集中检索 Blob 和 Clob 这两种数据类型的数据,该获得方法为:
Blob blob = rs.getBlob(); Clob clob = rs.getClob();
与其它数据类型不同,调用 getBlob() 和 getClob() 之后,需要使用 Blob 和 Clob 接口的方法访问数据。
CREATE TABLE clob_table(col1 Clob, col2 Clob, col3 Clob);
CREATE TABLE blob_table(col1 Blob, col2 Blob, col3 Blob);
CREATE TABLE clob_table(col1 oid, col2 oid, col3 oid);
CREATE TABLE blob_table(col1 oid, col2 oid, col3 oid);
String sql_select = "select * from clob_table"; Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(sql_select); int count = 1; /* 1.以字符串的方式显示 */ while (resultSet.next()) System.out.println("第" + count + "条记录"); Clob clob1 = resultSet.getClob(1); Clob clob2 = resultSet.getClob(2); Clob clob3 = resultSet.getClob(3); System.out.println("clob1:" + clob1.getSubString(1, (int) clob1.length())); System.out.println("clob2:" + clob2.getSubString(1, (int) clob2.length())); System.out.println("clob3:" + clob3.getSubString(1, (int) clob3.length())); count++; resultSet.close(); count = 1; resultSet = statement.executeQuery(sql_select); /* 2.取出clob对象,进行相关操作 */ while (resultSet.next()) System.out.println("第" + count + "条记录"); for (int i = 0; i < 3; i++) Clob clob = resultSet.getClob(i + 1); /* 使用getCharacterStream方法获得Clob列的数据。 */ Reader reader = clob.getCharacterStream(); StringWriter sWriter = new StringWriter(); int j = -1; while ((j = reader.read()) != -1) sWriter.write(j); /* 显示Clob列的数据。 */ String finalClob = new String(sWriter.getBuffer()); System.out.println(finalClob); count++; resultSet.close();
String sql_select = "select * from blob_table"; statement = connection.createStatement(); resultSet = statement.executeQuery(sql_select); int count = 1; /* 1.以字符串的方式显示 */ while (resultSet.next()) System.out.println("第" + count + "条记录"); Blob blob1 = resultSet.getBlob(1); Blob blob2 = resultSet.getBlob(1); Blob blob3 = resultSet.getBlob(1); System.out.println("blob1: " + new String(blob1.getBytes(1, (int) blob1.length()))); System.out.println("blob2: " + new String(blob2.getBytes(1, (int) blob2.length()))); System.out.println("blob3: " + new String(blob3.getBytes(1, (int) blob3.length()))); count++; resultSet.close(); count = 1; resultSet = statement.executeQuery(sql_select); /* 2.取出blob对象,进行相关操作 */ while (resultSet.next()) System.out.println("第" + count + "条记录"); for (int i = 0; i < 3; i++) Blob blob = resultSet.getBlob(i + 1); /* 使用getBinaryStream方法获得blob列的数据。 */ InputStream input = blob.getBinaryStream(); StringWriter sWriter = new StringWriter(); int j = -1; while ((j = input.read()) != -1) sWriter.write(j); /* 显示blob列的数据。 */ String finalblob = new String(sWriter.getBuffer()); System.out.println(finalblob); count++; resultSet.close();
6.2. 大对象数据的更新
PreparedStatement pstmt = conn.prepareStatement( "insert into bio(image,text) values(?,?)"); pstmt.setBlob(1,authorImage); pstmt.setClob(2,authorBio); pstmt.executeUpdate();
请看下面完整的示例。例 6-3、6-4、6-5只能在oracle兼容模式下执行,例 6-6 在 PG 和 oracle 兼容模式下均可执行。
CREATE TABLE clob_table(col1 Clob, col2 Clob, col3 Clob);
CREATE TABLE blob_table(col1 Blob, col2 Blob, col3 Blob);
/* * 插入 Clob 数据 String sql_insert = "insert into clob_table values(?,?,?)"; /* 从文件读取数据插入,以 setCharacterStream 方式插入 */ File file = new File("e:/test.xml"); Reader read1, read2, read3; read1 = new FileReader(file); read2 = new FileReader(file); read3 = new FileReader(file); preparedStatement = connection.prepareStatement(sql_insert); preparedStatement.setCharacterStream(1, read1); preparedStatement.setCharacterStream(2, read2); preparedStatement.setCharacterStream(3, read3); preparedStatement.execute(); /* 直接插入字符串 */ String str = "Welcome to Kingbase!"; preparedStatement = connection.prepareStatement(sql_insert); preparedStatement.setString(1, str); preparedStatement.setString(2, str); preparedStatement.setString(3, str); preparedStatement.execute();
/* * 插入 Blob 数据 String sql_insert = "insert into blob_table values(?,?,?)"; /* 从文件读取数据插入,以 setBinaryStream 方式插入 */ File file = new File("e:/test.xml"); InputStream input1, input2, input3; input1 = new FileInputStream(file); input2 = new FileInputStream(file); input3 = new FileInputStream(file); preparedStatement = connection.prepareStatement(sql_insert); preparedStatement.setBinaryStream(1, input1); preparedStatement.setBinaryStream(2, input2); preparedStatement.setBinaryStream(3, input3); preparedStatement.execute(); /* 直接插入字符串 */ String str = "Welcome to Kingbase!"; preparedStatement = connection.prepareStatement(sql_insert); preparedStatement.setBytes(1, str.getBytes()); preparedStatement.setBytes(2, str.getBytes()); preparedStatement.setBytes(3, str.getBytes()); preparedStatement.execute();
这个例子展示了如何使用 Clob 的 setCharacterStream、setAsciiStream 和 setString 方法更新 Clob 字段
/* * 使用 Clob 的 setAsciiStream、setCharacterStream 和 SetString 方法更新 * Clob 列。 String query = "Select * from clob_table for update"; Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query); if (resultSet.next()) Clob clob = resultSet.getClob(1); * 使用 setAsciiStream 方法更新 Clob 列,其中 clob.length() + 1 表示在 * 原值后追加新的值, * 原值为 “Welcome to Kingbase!”,更新后的值为 “Welcome to Kingbase! * Test has sucessful!”。 OutputStream os = clob.setAsciiStream(clob.length() + 1); String temp = "Test has sucessful!"; byte[] tempByte = temp.getBytes(); os.write(tempByte); os.close(); * 使用 setCharacterStream 方法更新 Clob 列,其中 clob.length() + 1 * 表示在原值后追加新的值, * 原值为 “Welcome to Kingbase!”,更新后的值为 “Welcome to Kingbase! * Welcome to Kingbase!”。 clob = resultSet.getClob(2); Writer writer = clob.setCharacterStream(clob.length() + 1); temp = "Welcome to Kingbase!"; writer.write(temp); writer.close(); * 使用 setString 方法更新 Clob 列,其中 temp.length() 表示原值的更新 * 位置,如果原值的长度 * 大于或者等于 temp.length() 的值,则新值代替对应位置的原值;否则原值 * 长度小于 temp.length() 的 * 值,更新时会报错。原值为 “Welcome to Kingbase!”,更新后的值为 * “Welcome to KingHello, Kingbase!”。 clob = resultSet.getClob(3); temp = "Hello, Kingbase!"; clob.setString(clob.length() + 1, temp);
这个例子展示了如何使用 Blob 的 setBinaryStream 和 setBytes 方法更新 Blob 字段
/* * 使用 Blob 的 setBinaryStream 和 setString 方法更新 blob 列。 String query = "Select * from blob_table for update"; Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query); if (resultSet.next()) Blob blob = resultSet.getBlob(1); * 使用 setBinaryStream 方法更新 blob 列,其中 blob.length() + 1 表示 * 在原值后追加新的值。 * 原值为 “Welcome to Kingbase!”,更新后的值为 “Welcome to Kingbase! * Welcome to Kingbase!”。 OutputStream output = blob.setBinaryStream(blob.length() + 1); String temp = "Welcome to Kingbase!"; output.write(temp.getBytes()); output.close(); * 使用 setBytes 方法更新 blob 列,其中 blob.length() + 1 表示原值的 * 更新位置,如果原值的长度大于或者等于 blob.length() + 1 的值,则新值 * 代替对应位置的原值;否则原值长度小于 blob.length() + 1 * 的值,更新时会报错。原值为 “Welcome to Kingbase!”,更新后的值为 * “Welcome to Kingbase!Hello, Kingbase!”。 blob = resultSet.getBlob(2);