LobToSP

如何把 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.zipclasses12.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 示例代码论坛。

寄送此页面
Printer View 打印机视图