如何把 Lob 作为参数从 Java 传递到数据库存储过程。
日期:2003 年 5 月 12 日
目标
在读完本文档后,您应该能够:
- 在 Java 程序中创建 LOB(Large OBject) 对象并将它作为参数传递给数据库存储过程。
本文档通过给出代码段和说明对此进行了阐述。
- 使用提供的指导运行此示例。
软件需求
- JDK1.3.x 或更高版本。可从此处下载。
- Oracle9i Database Release 2 或更新版本。可从此处下载。
- Oracle9i JDBC 驱动程序。可从此处下载。
注意:Oracle 数据库/客户端安装中提供了 Oracle JDBC 驱动程序。如果您安装了数据库/客户端, 您不需要单独下载 JDBC 启动程序。
说明
LOB 或大型对象是为了支持非结构的数据,这些数据难以分解为标准的组件,例如很难根据数据库的存储把它们分解为更细致的结构。LOB 能够存储非结构化的数据,并针对大容量的数据进行了优化,例如文本、图形图像、静止视频剪辑、全动作视频以及声音波形。它们提供了一种统一的方法来访问数据库内外的大型非结构化数据。
在 Oracle 8 和更高版本中,一个数据库表里可以有多个 LOB 列,而这些列也可以是不同的类型。LOB 的存储容量最高为 4GB。
Oracle 支持下面两种类型的 LOB。
- BLOB、CLOB、和 NCLOB:它们在数据库中要么存储在表中,要么存储在单独的段或表空间中。
- BLOB 能够存储大容量的二进制数据,典型例子有图形图像和照片。
- CLOB 能够存储大容量的字符数据,而且对于存储非结构化的 XML 文档很有用。
- NCLOB:由对应于为 Oracle 数据库定义的本地字符集的字符数据组成。
- BFILE:它们作为操作系统文件存储。
- BFILE 是一种 LOB 类型,它的值由二进制(“原始”)数据组成,而且存储在数据库表空间之外的服务器端操作系统文件中。
示例场景: 让我们假设在数据库中有一个故事表,该表有两列,id 和 CLOB。故事文本存储在 CLOB 列中。一个存储过程对数据库中的故事表进行更新。它接受两个输入参数:id 和 CLOB。下面是一段 SQL 代码示例。
数据库预备:
CREATE TABLE stories (id NUMBER(4), story CLOB);
INSERT INTO stories VALUES(1, EMPTY_CLOB());
commit;
-- The following procedure updates the CLOB in the table.
CREATE OR REPLACE PROCEDURE updateStory(id NUMBER, colValue IN CLOB) IS
BEGIN
UPDATE stories s SET s.story = colValue
WHERE s.id = id ;
commit;
-- Exception handling.
-- EXCEPTION
-- WHEN OTHERS THEN
--
END updateStory;
/
|
|
现在我们来看看各种把 CLOB 传递给存储过程的不同方法。可以用两种方法创建和操纵 CLOB 对象: 使用和不使用数据流。对于大容量数据,我们总是推荐使用数据流。
下面是两种方法的代码段。
不使用数据流而使用 oracle.sql.CLOB 类
.............
.............
// Using Oracle implementation of CLOB
import oracle.sql.CLOB;
// IO Imports
import java.io.Writer;
/*
* This method uses temporary clob to create the CLOB object.
*/
private static CLOB getCLOB( String clobData )
throws Exception {
CLOB tempClob = null;
try {
// create a new temporary CLOB
tempClob = CLOB.createTemporary( conn, true, CLOB.DURATION_SESSION );
// Open the temporary CLOB in readwrite mode to enable writing
tempClob.open( CLOB.MODE_READWRITE );
// Get the output stream to write
Writer tempClobWriter = tempClob.getCharacterOutputStream( );
// Write the data into the temporary CLOB
tempClobWriter.write( clobData );
// Flush and close the stream
tempClobWriter.flush( );
tempClobWriter.close( );
// Close the temporary CLOB
tempClob.close( );
} catch ( Exception exp ) {
// Free CLOB object
tempClob.freeTemporary( );
-- do something
}
return tempClob;
}
|
|
使用上面的 getCLOB 方法调用数据库存储过程:
..............................
..............................
CallableStatement cs = null;
oracle.sql.CLOB clob = null;
String clobData = null;
.......................
.......................
// read the file whose content has to be passed as CLOB.
String lineSep = System.getProperty("line.separator");
BufferedReader br = new BufferedReader(new FileReader(filename));
String nextLine = "";
StringBuffer sb = new StringBuffer();
while ((nextLine = br.readLine()) != null) {
sb.append(nextLine);
sb.append(lineSep);
}
// convert to string
clobData = sb.toString();
// call Stored DB procedure for updating clob column
cs = (CallableStatement)
conn.prepareCall( "begin updateStory(?,?); end;" );
// Create the CLOB object from the getCLOB method listed above.
clob = getCLOB(clobData);
// Bind the columns values
cs.setObject(1, "1" );
cs.setObject(2, clob );
............................
............................
|
|
通过数据流创建 CLOB 对象
..............................
..............................
public void callUpdateUsingStream(String id, String filename )
throws SQLException, FileNotFoundException {
CallableStatement cs = null;
.....................
.....................
conn.setAutoCommit(false);
String fileName = filename;
// Open the sample file as a stream
File file = new File(fileName);
FileInputStream fin = new FileInputStream(file);
// Call Stored DB procedure for updating clob column
cs = (CallableStatement)
conn.prepareCall( "begin updateStory(?,?); end;" );
// set id.
cs.setObject(1, id );
// use setAsciiStream to set the clob parameter.
cs.setAsciiStream(2,fin,(int)file.length());
cs.execute();
conn.setAutoCommit(true);
............................
............................
|
|
源代码:
点击此处查看完整的可运行源代码。
运行 Java 类
- 将完的源代码复制到一个目录中并存储为 TestCLob.java
- 在数据库中以用户 SCOTT 的身份运行上面列出的 SQL 脚本创建表和存储过程。
- 编辑 TestClob.java 并更改 getConnection() 方法以使用您自己的数据库参数。
// 连接到数据库。 conn = DriverManager.getConnection ("jdbc:oracle:thin:@::", "scott", "tiger");
- 在被复制的目录下的命令行提示符上,设置类路径以包含
Oracle JDBC 驱动程序类:classes12.zip 或 classes12.jar
- 编译 TestClob 类。
示例: javac -d .TestClob.java
- 通过给参数赋予值运行该类。
java TestClob
- 字符串值指明要更新的记录。
- 字符串值指明要更新的作为 clob 列内容的文件。
- 字符串值可以是 "true" 或 "False"。
"false" 将采用非数据流的方式,利用 callUpdate() 方法来更新 CLOB。 "true"将采用数据流的方式,利用 callUpdateUsingStreaming() 方法更新 CLOB。 示例: java TestClob "1" "d:\text.txt" "false"
- 运行下面的查询来检查数据库中的文件大小和 CLOB 大小,以验证更新的数据:
SQL> SELECT DBMS_LOB.GETLENGTH(story) FROM stories
资源
OTN 上的示例程序引用:
总结
本文档试图解释和举例说明如何在 Java 程序中创建 CLOB 对象并将它传递给数据库存储过程。
请将关于此示例的评论意见输入 OTN 示例代码论坛。
|