Wie Sie schreiben / aktualisieren von Oracle-blob in eine zuverlässige Möglichkeit?

Ich versuche zu schreiben und Aktualisierung eines pdf-Dokuments in einem blob-Spalte, aber ich bin nur in der Lage, zur Aktualisierung der blob nur schreiben mehr Daten als die vorherigen gespeicherten Daten.
Wenn ich versuche zu aktualisieren, die blob-Spalte mit einem kleineren Dokument-Daten bekomme ich nur eine beschädigte pdf-Datei.

Zuerst der blob-Spalte initialisiert wurde mit empty_blob () - Funktion. Ich habe die Beispiel-Java-Klasse unten, um zu testen, dieses Verhalten. Ich es das erste mal mit 'true' als ersten parameter der main Methode so in der ersten Reihe dort gespeichert ein Dokument über 31kB und in der zweiten Zeile gibt es ein Dokument von 278kB.
Dann habe ich es mit 'false' als parameter, auf diese Weise die zwei Zeilen aktualisiert werden soll der Austausch der Dokumente. Das Ergebnis ist, dass ich eine richtige Ergebnis nur, wenn ich Schreibe mehr Daten als die bereits vorhandenen.

Wie ist es möglich, zu schreiben, eine Methode, die schreibt und updates ein blob in einer zuverlässigen Weise, ohne worring über binäre Daten Größe?

import static org.apache.commons.io.IOUtils.copy;

import java.io.FileInputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import oracle.jdbc.OracleDriver;
import oracle.jdbc.OracleResultSet;
import oracle.sql.BLOB;

import org.apache.commons.lang.ArrayUtils;
/**
 * Prerequisites:
 * 1) a table named 'x' must exists [create table x (i number, j blob);] 
 * 2) that table should have two columns [insert into x (i, j) values (1, empty_blob()); insert into x (i, j) values (2, empty_blob()); commit;]
 * 3) download lsp.pdf from http://www.objectmentor.com/resources/articles/lsp.pdf
 * 4) download dotguide.pdf from http://www.graphviz.org/Documentation/dotguide.pdf
 */
public class UpdateBlob {
    public static void main(String[] args) throws Exception {
        processFiles(new String[]{"lsp.pdf", "dotguide.pdf"}, Boolean.valueOf(args[0]));
    }

    public static void processFiles(String [] fileNames, boolean forward) throws Exception {
      if(!forward){
        ArrayUtils.reverse(a);
      }
      int idx = 1;
      for(String fname : fileNames){
        insert(idx++, fname);
      }
  }

    private static void insert(int idx, String fname) throws Exception{
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            DriverManager.registerDriver(new OracleDriver());
            conn = DriverManager.getConnection("jdbc:oracle:thin:@"+db+":"+port+":"+sid, user, pwd);
            ps = conn.prepareStatement("select j from x where i = ? for update");
            ps.setLong(1, idx);

            rs = ps.executeQuery();

            if (rs.next()) {
                FileInputStream instream = new FileInputStream(fname);
                BLOB blob = ((OracleResultSet)rs).getBLOB(1);
                OutputStream outstream = blob.setBinaryStream(1L);
                copy(instream, outstream);
                instream.close();
                outstream.close();
            }
            rs.close();
            ps.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new Exception(e);
        }
    }
}

Oracle-version: 11.1.0.7.0 - 64bit

Ich habe sogar versucht die standard-JDBC-API ohne Verwendung von Oracle-spezifische (wie im Beispiel oben), ohne Erfolg.

Vielleicht bin ich etwas fehlt offensichtlich... Aber wo ist der copy Methode definiert? Meine Vermutung ist, dass die copy Methode ist nicht zu tun, was Sie erwarten und ist nur Austausch der ersten N bytes, wenn die neuen Daten kleiner als die alten Daten.
Btw: Sie sollten nicht öffnen Sie eine neue Verbindung für jeden Aufruf der Funktion. Das ist, tot zu sein langsam.
copy Methode ist definiert in den org.apache.Unterhaus.io.IOUtils Klasse. Es gibt einen statischen import am Anfang des Codes. Statische Importe macht das weniger lesbar, aber ich denke, dass in einigen Fällen ist es bequem, Sie zu benutzen.
Der code oben ist nur eine wirklich schnelle POC. Ich benutze immer ein connection-pool zu verwalten, db-Verbindung.

InformationsquelleAutor alexyz78 | 2011-12-01

Schreibe einen Kommentar