Comment rédiger / mettre à jour Oracle blob dans un moyen fiable?

Je suis en train d'écrire et de mettre à jour un document pdf dans une colonne blob mais je suis juste en mesure de mettre à jour le blob n'écrivant plus de données que les précédentes données stockées.
Si j'essaie de mettre à jour la colonne blob avec un petit document les données que je obtenir seulement un corrompu pdf.

D'abord la colonne blob a été initialisé à l'aide de empty_blob() fonction. J'ai écrit l'exemple de la classe Java ci-dessous pour tester ce comportement. Je le lance pour la première fois avec le "vrai" comme premier paramètre de la principal méthode dans la première ligne il y a stocké un document d'environ 31 ko et dans la deuxième ligne, il y a un document de 278ko.
Puis je le lance avec "faux" comme paramètre, de cette façon, les deux lignes doivent être mis à jour en échangeant les documents. Le résultat est que j'obtiens un résultat correct que lorsque j'écris plus de données que l'existant.

Comment est-il possible d'écrire une méthode qui écrit et met à jour une goutte de manière fiable sans worring sur des données binaires de taille?

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

J'ai même essayé de la norme API JDBC sans l'aide d'Oracle spécifique (comme dans l'exemple ci-dessus), sans succès.

Peut-être que je suis absent quelque chose d'évident... Mais où est le copy méthode définie? Mon intuition est que le copy méthode n'est pas de faire ce que vous attendez et est remplacer uniquement les N premiers octets si les nouvelles données sont plus petites que les anciennes données.
Btw: vous ne devez pas ouvrir une nouvelle connexion pour chaque appel de la fonction. Qui va être très lente.
copy méthode est définie dans le org.apache.commons.io.IOUtils de classe. Il y a une statique à l'importation au début du code. Statique des importations rend moins lisible, mais je pense que dans certains cas, il est pratique à utiliser.
Le code ci-dessus est juste un vraiment rapide POC. J'ai toujours utiliser un pool de connexion pour gérer la connexion db.

OriginalL'auteur alexyz78 | 2011-12-01