使用大对象
Blob
,Clob
和NClob
Java 对象的一个重要功能是您可以操作它们,而不必将其所有数据从数据库服务器带到 Client 端计算机。一些实现通过定位器(逻辑指针)来代表这些类型的实例,该定位器指向该实例所代表的数据库中的对象。因为BLOB
,CLOB
或NCLOB
SQL 对象可能非常大,所以使用定位符可使性能大大提高。但是,其他实现完全在 Client 端计算机上实现大型对象。
如果要将BLOB
,CLOB
或NCLOB
SQL 值的数据带到 Client 端计算机,请使用为此 Object 提供的Blob
,Clob
和NClob
Java interface中的方法。这些大型对象类型的对象具体化了它们表示为流的对象的数据。
涵盖以下主题:
将大对象类型的对象添加到数据库
以下来自ClobSample.addRowToCoffeeDescriptions
的摘录将CLOB
SQL 值添加到表COFFEE_DESCRIPTIONS
。 Clob
Java 对象myClob
包含fileName
指定的文件的内容。
public void addRowToCoffeeDescriptions(
String coffeeName, String fileName)
throws SQLException {
PreparedStatement pstmt = null;
try {
Clob myClob = this.con.createClob();
Writer clobWriter = myClob.setCharacterStream(1);
String str = this.readFile(fileName, clobWriter);
System.out.println("Wrote the following: " +
clobWriter.toString());
if (this.settings.dbms.equals("mysql")) {
System.out.println(
"MySQL, setting String in Clob " +
"object with setString method");
myClob.setString(1, str);
}
System.out.println("Length of Clob: " + myClob.length());
String sql = "INSERT INTO COFFEE_DESCRIPTIONS " +
"VALUES(?,?)";
pstmt = this.con.prepareStatement(sql);
pstmt.setString(1, coffeeName);
pstmt.setClob(2, myClob);
pstmt.executeUpdate();
} catch (SQLException sqlex) {
JDBCTutorialUtilities.printSQLException(sqlex);
} catch (Exception ex) {
System.out.println("Unexpected exception: " + ex.toString());
} finally {
if (pstmt != null)pstmt.close();
}
}
下面的行创建一个Clob
Java 对象:
Clob myClob = this.con.createClob();
下一行检索一个流(在本例中为名为clobWriter
的Writer
对象),该流用于将字符流写入Clob
Java 对象myClob
。方法ClobSample.readFile
写入此字符流;该流来自String
fileName
指定的文件。方法参数1
表示Writer
对象将在Clob
值的开头开始写入字符流:
Writer clobWriter = myClob.setCharacterStream(1);
ClobSample.readFile
方法逐行读取文件fileName
指定的文件,并将其写入writerArg
指定的Writer
对象:
private String readFile(String fileName, Writer writerArg)
throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String nextLine = "";
StringBuffer sb = new StringBuffer();
while ((nextLine = br.readLine()) != null) {
System.out.println("Writing: " + nextLine);
writerArg.write(nextLine);
sb.append(nextLine);
}
// Convert the content into to a string
String clobData = sb.toString();
// Return the data.
return clobData;
}
以下摘录创建了一个PreparedStatement
对象pstmt
,该对象将Clob
Java 对象myClob
插入到COFFEE_DESCRIPTIONS
:
PreparedStatement pstmt = null;
// ...
String sql = "INSERT INTO COFFEE_DESCRIPTIONS VALUES(?,?)";
pstmt = this.con.prepareStatement(sql);
pstmt.setString(1, coffeeName);
pstmt.setClob(2, myClob);
pstmt.executeUpdate();
检索 CLOB 值
方法ClobSample.retrieveExcerpt
从其列值COF_NAME
等于coffeeName
参数指定的String
值的行中检索存储在COFFEE_DESCRIPTIONS
的COF_DESC
列中的CLOB
SQL 值:
public String retrieveExcerpt(String coffeeName, int numChar)
throws SQLException {
String description = null;
Clob myClob = null;
PreparedStatement pstmt = null;
try {
String sql =
"select COF_DESC " +
"from COFFEE_DESCRIPTIONS " +
"where COF_NAME = ?";
pstmt = this.con.prepareStatement(sql);
pstmt.setString(1, coffeeName);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
myClob = rs.getClob(1);
System.out.println("Length of retrieved Clob: " +
myClob.length());
}
description = myClob.getSubString(1, numChar);
} catch (SQLException sqlex) {
JDBCTutorialUtilities.printSQLException(sqlex);
} catch (Exception ex) {
System.out.println("Unexpected exception: " + ex.toString());
} finally {
if (pstmt != null) pstmt.close();
}
return description;
}
下一行从ResultSet
对象rs
检索Clob
Java 值:
myClob = rs.getClob(1);
下一行从myClob
对象检索一个子字符串。子字符串 从值myClob
的第一个字符开始,并具有numChar
中指定的连续字符数,其中numChar
是整数。
description = myClob.getSubString(1, numChar);
添加和检索 BLOB 对象
添加和检索BLOB
SQL 对象类似于添加和检索CLOB
SQL 对象。使用Blob.setBinaryStream
方法检索OutputStream
对象,以写入Blob
Java 对象(称为方法)表示的BLOB
SQL 值。
释放大对象持有的资源
Blob
,Clob
和NClob
Java 对象至少在创建它们的事务期间保持有效。在 Long 期运行的事务中,这可能导致应用程序资源不足。应用程序可以通过调用free
方法来释放Blob
,Clob
和NClob
资源。
在以下摘录中,调用方法Clob.free
以释放为先前创建的Clob
对象保留的资源:
Clob aClob = con.createClob();
int numWritten = aClob.setString(1, val);
aClob.free();