Java: BLOB in Oracle DB per OutputStream schreiben!

KingSized

Grünschnabel
Hallo,

ich habe schon seit 5 Tagen ein Problem, welches ich nicht gelöst bekomme, hoffe jemand kann mir so schnell wie möglich weiter helfen.

Also ich versuche einen BLOB (in meinem Fall eine einfache jpg) in eine Oracle DB zu schreiben.
Mein Problem dabei ist, dass es nicht Funktioniert ich bekomme keine Exception aber auch kein Bild in die Datenbank.

Hier ist der Code:

Code:
  try {
      dbCon.setAutoCommit(true);
      st.execute("update <Tabelle1> set <BlobSpalte> =  EMPTY_BLOB() WHERE ID = 5");
      dbCon.setAutoCommit(false);
      ResultSet rs = st.executeQuery("select <BlobSpalte> from  <Tabelle1>  where ID = 5 for update");
      
       if (rs.first()) {
         BLOB blob = ((OracleResultSet) rs).getBLOB("<BlobSpalte>");
         File fl = new File("<jpg-Pfad>");
         FileInputStream fis = new FileInputStream(fl);
         OutputStream ostream = blob.getBinaryOutputStream();
         byte[] buffer = new byte[(int) fl.length()];
         while (fis.read(buffer) != -1) 
           ostream.write(buffer);
         ostream.close();
         fis.close();
       }
     } catch (Exception e) {
       e.printStackTrace();
     }

Das Ganze ist auf einen Button gelegt und das Einfügen des EMPTY_BLOB() funktioniert Problemlos.

Der Code selbst sollte laut der Oracle Docu funktionieren und die Benötigten Imports sind auch alle Vorhanden.

Zur Info die Connection wird über den Thin-Treiber Realisisert.

Würde mich über möglichst schnelle Hilfe freuen.
 
So hab jetzt ein Beispiel gefunden: http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96591/adl06faq.htm#127885

Mein Code sieht nun dementsprechend so aus:

Code:
      st.execute("update <tabelle> set <spalte>= EMPTY_BLOB() WHERE ID = 1");
      dbCon.setAutoCommit(false);
      ResultSet rs = st.executeQuery("select <spalte> from <Tabelle> where ID = 1");

      if (rs.next()) {
 
        BLOB blob = ((OracleResultSet) rs).getBLOB("<spalte>");
        File fl = new File("<Dateipfad>");
        FileInputStream fis = new FileInputStream(fl);
        OutputStream ostream = blob.getBinaryOutputStream();
        byte[] buffer = new byte[(int) fl.length()];
        int length = 0;
        while ((length = fis.read(buffer)) != -1) {
          ostream.write(buffer, 0, length);
        }
        fis.close();
        ostream.close();
        rs.close();
      }

Bei diesem Code bekomme ich sogar eine Exception:

java.io.IOException: ORA-22920: Zeile mit dem LOB-Wert ist nicht gesperrt

Sobald ich in dem executeQuery ein "for Update" im SQL-Befehl anhänge kommt diese Exception nicht mehr, aber auch kein Bild in die Datenbank.

Kann mir jemand weiterhelfen?
 
OK hab den Fehler selbst gefunden . . . man muss den SQL-Befehl mit dem FOR UPDATE benutzen und auch den AUTOCOMMIT ausschalten.
Sobald man diesen ausschaltet sollte man nicht vergessen mauell zu Commiten :)

Jetzt hab ich natürlich ein neues Problem:

Das Bild wird nicht vollständig in die Datenbank geschrieben. . .
Im Debuger kann man sehen, dass das ByteArray genauso groß ist wie das Bild.
Der Outputstream wird auch bis zu diesem Byte geschrieben aber in der Datenbank fehlen dann bis zu 30kb . . .
 
Ich würde den buffer nicht so groß machen wie die Datei sondern schon auf ein Sinnvolles Maß wie ein KB begrenzen.

Dann eventuell nach dem schreiben nochmal ein flush aufrufen.
 
Der Buffer muss so groß sein wie das Bild ,da der Inputstream in den Buffer geschrieben wird und dann der Buffer in den Outputstream geschrieben wird.
Der Buffer ist nichts weiter als ein ByteArray. Wenn ich ihn auf 1kb begrenzen würde könnte ich auch keine Bilder in die Datenbank einfügen die größer als 1kb sind.

Damit dasganze mal in einem Kontext steht:

Ich mache Screenshots, welche dann in eine Datenbank geschrieben werden. . .

und dies ist der derzeitige Code:

Code:
 if (rs.first()) {
        BLOB blob = ((OracleResultSet) rs).getBLOB("<Spalte>");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(bimage, "jpg", byteArrayOutputStream);
        byte[] buffer = byteArrayOutputStream.toByteArray();
        OutputStream ostream = blob.getBinaryOutputStream();
        ostream.write(buffer);
        dbCon.commit();
        rs.close();
      }

bimage ist ein buffered image,welches ich vom Clipboard bekomme.
Die Größe des buffers wird nun automatisch durch die Größe des buffered image bestimmt.
 
Zuletzt bearbeitet:
Im obigen Beispiel hast du das ganze noch aus einer Datei und über eine Schleife ausgelesen. Und in einer Schleife setzt man den Puffer normalerweise auf 1KB. Da es sich um eine Schleife handelt wird dann nach und nach immer ein KB aus dem Input gelesen und in den Output geschrieben. Das hat nichts mit der Dateigröße zu tun.

So wie du es jetzt machst rufst du ja gar kein flush oder close mehr auf. Dann können ja auch nicht alle Daten in der Datenbank ankommen.
 
Habe die Schleife falsch verstanden. . .jetzt weiß ich auch was du meinst.

Mit dem zweiten Beispiel ist mir vorhin schon selbst aufgefallen, dass ich den flush auskommentiert hatte^^

Funktioniert jetzt alles Reibungslos großen Dank für die Hilfe.
 

Neue Beiträge

Zurück