Overcomplicated Oracle JDBC BLOB-Behandlung
Wenn ich das web für die Suche einfügen von BLOBs in Oracle-Datenbank mit dem jdbc-thin-Treiber, die meisten Webseiten empfehlen eine 3-Schritt-Ansatz:
- einfügen
empty_blob()
Wert. - wählen Sie die Zeile mit
for update
. - legen Sie den realen Wert.
Dies funktioniert gut für mich, hier ist ein Beispiel:
Connection oracleConnection = ...
byte[] testArray = ...
PreparedStatement ps = oracleConnection.prepareStatement(
"insert into test (id, blobfield) values(?, empty_blob())");
ps.setInt(1, 100);
ps.executeUpdate();
ps.close();
ps = oracleConnection.prepareStatement(
"select blobfield from test where id = ? for update");
ps.setInt(1, 100);
OracleResultSet rs = (OracleResultSet) ps.executeQuery();
if (rs.next()) {
BLOB blob = (BLOB) rs.getBLOB(1);
OutputStream outputStream = blob.setBinaryStream(0L);
InputStream inputStream = new ByteArrayInputStream(testArray);
byte[] buffer = new byte[blob.getBufferSize()];
int byteread = 0;
while ((byteread = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, byteread);
}
outputStream.close();
inputStream.close();
}
Gibt es einige Webseiten, wo die Autoren empfehlen die Verwendung einer einfacheren 1-Schritt Lösung. Vorherigen Beispiel mit dieser Lösung:
Connection oracleConnection = ...
byte[] testArray = ...
PreparedStatement ps = oracleConnection.prepareStatement(
"insert into test(id, blobfield) values(?, ?)");
BLOB blob = BLOB.createTemporary(oracleConnection, false, BLOB.DURATION_SESSION);
OutputStream outputStream = blob.setBinaryStream(0L);
InputStream inputStream = new ByteArrayInputStream(testArray);
byte[] buffer = new byte[blob.getBufferSize()];
int byteread = 0;
while ((byteread = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, byteread);
}
outputStream.close();
inputStream.close();
ps.setInt(1, 100);
ps.setBlob(2, blob);
ps.executeUpdate();
ps.close();
Der zweite code ist viel einfacher, also meine Frage ist: Was ist der Punkt, der erste (populär -) Lösung? Ist es (war es) eine Art von Zwang für die zweite Lösung (Oracle-server-version und-Nummer, jdbc-Treiber, die version, die Größe des blob,...)? Ist die erste Lösung besser (Geschwindigkeit, Speicherverbrauch,...)? Die Gründe für die nicht mit der einfachen zweiten Ansatz?
Die exakt gleiche Frage gilt für die CLOB-Felder.
InformationsquelleAutor der Frage asalamon74 | 2009-05-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den update-Ansatz, den Sie erwähnen im ersten Fall kann geschrieben werden Verwendung von reinem JDBC-code und reduzieren damit Ihre Abhängigkeit von Oracle-spezifische Klassen. Dies könnte hilfreich sein, wenn Sie Ihre app muss sein, Datenbank-agnostisch.
Für MSSQL ich verstehe, dass die Verriegelung syntax ist anders:
InformationsquelleAutor der Antwort Mr. Shiny and New 安宇
Andere Sicht von Oracle DBA. Sonne Jungs haben sehr schlechten job, wenn Sie so konzipiert JDBC-standards(1.0, 2.0, 3.0, 4.0). BLOB steht für large object und kann daher sehr groß sein. Es ist etwas, das kann nicht gespeichert werden, in die JVM-heap. Oracle denkt der BLOBs so etwas wie file-handles(es Tatsache, Sie rufen dann "lob-Locator-Punkte"). LOBS können nicht erstellt werden über Konstruktor und nicht Java-Objekte. Auch LOB-Locator(oracle.sql.BLOB) kann nicht erstellt werden über Konstruktor - Sie MÜSSEN erstellt werden, in der DB-Seite.
In Oracle gibt es zwei Möglichkeiten, wie man erstellen Sie ein LOB.
DBMS_LOB.CREATETEMPORATY - der locator zurückgegeben, in diesem Fall Punkte in den temporären tablespace. All das schreibt/liest gegen dieses locator wird über das Netz gesendet werden auf DB-server. Nichts ist gespeichert in JVM-heap.
Aufruf Funktion EMPTY_BLOB.
INSERT INTO T1(NAME, DATEI) VALUES (".avi", EMPTY_BLOB()) RETURNING DATEI INTO ?;
In diesem Fall zurückgegeben lob-locator-Punkte in Daten-tablespace. All das schreibt/liest gegen dieses locator wird über das Netz gesendet werden auf DB-server. Alle Schreibvorgänge werden "bewacht" von schreibt in die redo-logs. Nichts ist gespeichert in JVM-heap. Die Rückkehr-Klausel nicht unterstützt wurde durch die JDBC-standards (1.0, 2.0), daher findet man viele Beispiele im internet, wo die Menschen empfehlen-Ansatz in zwei Schritten: "INSERT...; SELECT ... FOR UPDATE;"
Oracle lobs muss im Zusammenhang mit einer Datenbank-Verbindung, können Sie nicht verwendet werden, wenn
DB-Verbindung verloren/geschlossen/oder ("commited"). Sie kann nicht übergeben werden, von einer Verbindung zur anderen.
Sie zweite Beispiel arbeiten können, aber wird übermäßig viel kopieren, wenn Sie Daten aus temporären tablespace in Daten-tablespace.
InformationsquelleAutor der Antwort Ivan
Dem Oracle-server ' s LOB-die Handhabung ist ziemlich schlecht und leiden können schwerwiegende performance-Probleme (z.B. massive übernutzung der redo-log), so dass die erste Lösung kann ein Weg sein, um diese.
Ich würde vorschlagen, versucht, beide Ansätze. wenn Sie einen kompetenten DBA, können Sie in der Lage sein zu beraten, welche Vorgehensweise hat die geringsten Auswirkungen auf den server.
InformationsquelleAutor der Antwort skaffman
Eine interessante Sache mit JDBC können Sie ein upgrade eher aggressiv, um die neuesten Treiber und arbeiten mit JDBC-4.0-Funktionen. Der oracle-JDBC-Treiber wird die Arbeit mit älteren Datenbank-Versionen verwenden, so können Sie eine 11g-Marken-JDBC-Treiber gegen einen 10g-Datenbank. Die Oracle Datenbank 11g JDBC kommt in zwei Geschmacksrichtungen: ojdbc5.jar für Java 5 (d.h., JDK 1.5) und ojdbc6.jar für Java 6 (d.h., JDK 1.6). Die ojdbc6.jar unterstützt die neue JDBC-4.0-Spezifikation.
Mit den neueren Treibern/jdbc 4.0 können Sie erstellen, Blobs und Clobs aus dem connection-Objekt:
InformationsquelleAutor der Antwort Brian
Diese Aussage :
gibt Probleme, wenn ich mit oracle-thin-client ojdbc14.jar, "nicht Unterstützte Funktionen"
So, ich hatte zu umgehen, indem Sie :
InformationsquelleAutor der Antwort
Sofern die CLOB-Daten klein genug, um passen in den Speicher, ohne Sprengung, können Sie einfach erstellen Sie eine vorbereitete Anweisung und rufen Sie einfach
Möglicherweise gibt es andere Größe Einschränkungen, aber es scheint zu funktionieren für die Größen, die wir zu tun haben (max 500kB).
InformationsquelleAutor der Antwort Quartz
Einige watchouts gefunden für die zweite Lösung
Ich bin mit ojdbc6.jar - das aktuelle release und für die Aussage 'zweite Lösung':
Habe ich zu release blob nach der Anweisung abgeschlossen ist - oder anders blob ist geschlossen, wenn die session geschlossen wird (das kann lange dauern, mit Verbindungs-pooling).
Sonst kann man sehen gesperrten Ressourcen:
Ein weiteres problem mit temporären BLOBs ist die Notwendigkeit zu vergeben temporary tablespace:
als pro-Dokumentation http://docs.oracle.com/cd/E11882_01/appdev.112/e18294.pdf
Die Verwaltung von Temporären Tablespace für Temporäre LOBs
Temporärer tablespace verwendet wird, zum speichern von temporären LOB-Daten
InformationsquelleAutor der Antwort j23
Fand ich einen einfachen Aufruf
setObject(pos, byte[])
funktioniert für meinen Fall.Von Datenbank-Programmierung mit JDBC und Java Von George Reese,
InformationsquelleAutor der Antwort Kirby
Wenn Größe, das einfügen von BLOB größer ist als blob.getBufferSize(), Transaktion verpflichtet, sobald die ersten chunk geschrieben, um die db als default-Wert des autoCommit-Eigenschaft jdbc-Verbindung ist wahr, und weitere Stücke schreibt nicht als db behandelt Sie als neue Transaktionen. Es wird vorgeschlagen, wie folgt aus:
a) stellen Sie den jdbc-Verbindung autoCommit-Eigenschaft auf false.
b) Explizit commit der Transaktion nach dem hochladen das ganze BLOB.
InformationsquelleAutor der Antwort AVA