6

我正在尝试使用 JDBC 在 Oracle 数据库上创建 Java 源对象。

我要创建的源如下:

create or replace and resolve java source named "BlobIO" as package dbjava;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.io.*;


public class BlobIO {

    /**
     * Stores a blob into a local file (or even UNC-path)
     * @param blob The blob locator that should be stored in a file
     * @param filename The filename to write to
     * @param bufferSize The buffer size for data transfer
     * @return 1 if successful, 0 if failed
     */
    public static int blobToFile(java.sql.Blob blob, String filename, int bufferSize)
    {
        OutputStream os = null;
        InputStream is = null;
        boolean fail = true;
        try {

            is = blob.getBinaryStream();
            os = new FileOutputStream(filename);
            int amountRead = 0;
            byte[] buffer = new byte[bufferSize];
            while ((amountRead = is.read(buffer, 0, buffer.length)) != -1) {
                os.write(buffer, 0, amountRead);
            }
            is.close();
            os.flush();
            os.close();
            fail = false;
        } catch (IOException ex) {
            new File(filename).delete();
            System.err.println("Could not store blob to file.");
            System.err.println("File : " + filename);
            System.err.println("Reason : " + ex.getClass().getName() + " : " + ex.getMessage());
            fail = true;
        } catch (SQLException ex) {
            new File(filename).delete();
            System.err.println("Could not store blob to file.");
            System.err.println("File : " + filename);
            System.err.println("Reason : " + ex.getClass().getName() + " : " + ex.getMessage());
            fail = true;
        } finally {
            try {is.close();} catch (Exception ex) {}
            try {os.flush();} catch (Exception ex) {}
            try {os.close();} catch (Exception ex) {}
        }
        return fail? 0:1;
    }

    /**
     * Stores a blob into a local file (or even UNC-path)
     * @param query The query that should select ONLY the blob field
     * @param filename The filename to write to
     * @param bufferSize The buffer size for data transfer
     * @return 1 if successful, 0 if failed
     */
    public static int blobToFile(String query, String filename, int bufferSize) {
        try {
            Connection conn = DriverManager.getConnection("jdbc:default:connection:");
            Statement stmt = conn.createStatement();
            ResultSet rset = stmt.executeQuery(query);
            InputStream is;


            if (rset.next())
            {
                int ret = blobToFile(rset.getBlob(1), filename, bufferSize);
                if (rset.next())
                {
                    new File(filename).delete();
                    System.err.println("Could not store blob to file.");
                    System.err.println("Blob query : " + query);
                    System.err.println("File : " + filename);
                    System.err.println("Reason : too many rows");
                    rset.close();
                    stmt.close();
                    return 0;
                } else {
                    rset.close();
                    stmt.close();
                    return ret;
                }
            } else {
                System.err.println("Could not store blob to file.");
                System.err.println("Blob query : " + query);
                System.err.println("File : " + filename);
                System.err.println("Reason : no records retrieved by query");
                rset.close();
                stmt.close();
                return 0;
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return 0;
        }

    }

}
/

我尝试过CallableStatement使用 execute 方法,这给了我error: "Missing IN/OUT parameters" 当我尝试在普通Statement对象上使用 execute 方法时出现错误:"

Non supported SQL92 token at position: 262"

任何人都知道我做错了什么?似乎也无法在谷歌上找到任何东西。

编辑:这是我用来尝试执行脚本的代码(字符串sql包含您可以在上面看到的脚本,变量connConnection对象。

CallableStatement stat = conn.prepareCall(sql);
stat.setEscapeProcessing(false);
stat.execute();

如果我尝试仅使用 Statement 它是这样的:

Statement stat = conn.createStatement();
stat.execute(sql);
4

2 回答 2

7

好的,最终发现了问题,它需要CallableStatementsetEscapeProcessing(false).

于 2013-04-26T12:59:06.303 回答
2

请发布一个完整的完整示例。您的代码正在运行,以下是我的11.1.0.7.0数据库中的结果。首先是设置:

SQL> create or replace directory TMP as '/tmp';

Directory created

SQL> CREATE TABLE testBlob (a BLOB);

Table created

SQL> INSERT INTO testBlob VALUES (utl_raw.cast_to_raw('StackOverflow'));

1 row inserted

第一个功能:

SQL> CREATE OR REPLACE FUNCTION blob2File(p_blob BLOB,
  2                                       p_path VARCHAR2,
  3                                       p_buffer NUMBER)
  4    RETURN NUMBER AS
  5  LANGUAGE JAVA NAME
  6     'dbjava.BlobIO.blobToFile(java.sql.Blob,
  7                               java.lang.String,
  8                               int) return int';
  9  /

Function created

SQL> DECLARE
  2     l_blob   BLOB;
  3     l_return INT;
  4  BEGIN
  5     SELECT * INTO l_blob FROM testBlob;
  6     l_return := blob2File(l_blob, '/tmp/test.blob', 1024);
  7     dbms_output.put_line(l_return);
  8  END;
  9  /

1

对于第二个功能:

SQL> CREATE OR REPLACE FUNCTION queryBlob2File(p_query VARCHAR2,
  2                                            p_path VARCHAR2,
  3                                            p_buffer NUMBER) RETURN NUMBER AS
  4  LANGUAGE JAVA NAME
  5     'dbjava.BlobIO.blobToFile(java.lang.String,
  6                               java.lang.String,
  7                               int) return int';
  8  /

Function created

SQL> DECLARE
  2     l_query  VARCHAR2(1000);
  3     l_return INT;
  4  BEGIN
  5     l_query := 'SELECT * FROM testBlob';
  6     l_return := queryBlob2File(l_query, '/tmp/test.blob', 1024);
  7     dbms_output.put_line(l_return);
  8  END;
  9  /

1

PL/SQL procedure successfully completed

您可以使用该UTL_FILE包直接在 PL/SQL 中处理文件:

SQL> DECLARE
  2     l_file utl_file.file_type;
  3     l_line VARCHAR2(1024);
  4  BEGIN
  5     l_file := utl_file.fopen(location => 'TMP',
  6                              filename => 'test.blob',
  7                              open_mode => 'R');
  8     utl_file.get_line(l_file, l_line);
  9     dbms_output.put_line(l_line);
 10     utl_file.fclose(l_file);
 11  END;
 12  /

StackOverflow
于 2013-04-22T08:34:02.240 回答