Create Java on Oracle database with JDBC

2019-04-29 10:28发布

问题:

I'm trying to create a Java source object on an oracle database using JDBC.

The source I want to create is the following:

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;
        }

    }

}
/

I have tried with a CallableStatement using the execute method and this gives me the error: "Missing IN/OUT parameters" When I try using the execute method on a normal Statement object I get the error: "

Non supported SQL92 token at position: 262"

Anyone has any idea what I'm doing wrong? Can't seem to find anything on google either.

EDIT: This the code I use to try to execute the script (the String sql contains the script you can see above, the variable conn is the Connection object.

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

If i try with just Statement it is this:

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

回答1:

Ok found the problem eventually, it needed to be CallableStatement with setEscapeProcessing(false).



回答2:

Please post a complete thorough example. Your code is working, following is the result on my 11.1.0.7.0 db. First the setup:

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

The first function:

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

For the second function:

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

You can use the UTL_FILE package to deal with files directly in 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


标签: java oracle jdbc