2010-01-15 24 views
19

Sto provando a recuperare un blob da un database postgres utilizzando i driver jdbc. È troppo grande da avere in memoria, quindi voglio riprodurlo in streaming come download. Ho provato a utilizzare il metodo getBinaryStream su ResultSet, ma si scopre che questo metodo in realtà legge tutto in memoria, quindi non funziona per file di grandi dimensioni.Postgresql, JDBC e flussi BLOB

Apparentemente, è possibile utilizzare il metodo getBlob sul set di risultati e ottenere presumibilmente l'inputstream dal blob e passare da lì, ma è lì che si verifica il problema.

PreparedStatement ps = con.prepareStatement("select data from file_data WHERE ID = ?"); 
ps.setLong(1,file.fileData.id) 
ResultSet rs = ps.executeQuery() 
if(rs.next()){ 
     rs.getBlob("data") 

Questo è il codice che sto utilizzando. Quando si arriva a quella ultima linea è buttare fuori un errore che non riesco a dare un senso ...

org.postgresql.util.PSQLException: valore di Bad per tipo lungo: xxxxxx

"xxxxxx "quindi è il contenuto del file. Potete immaginare che diventa piuttosto lungo, ma non proprio il punto.

Sono bloccato qui. Qualcuno ha qualche idea su cosa sta succedendo? Diamine, avrò anche metodi alternativi per lo streaming di grandi quantità di blob come download.

+0

Nel mio caso era 'rs.getBlob (...)' invece di 'rs.getBinaryStream (...)'. Non è mai tardi per imparare JDBC. –

risposta

17

La mia ipotesi è, che hai mescolato BLOB di stile OID e BYTEA. Gli oggetti binari di grandi dimensioni vengono memorizzati indirettamente con le colonne OID in Postgres. I dati del file attuale vengono memorizzati da Postgres al di fuori della tabella del database. La colonna contiene solo un identificatore di oggetto che è associato internamente al blob. Per esempio: se si utilizza il metodo ResultSet#getBlob(String), che si prevede

janko=# CREATE TABLE blobtest1 (name CHAR(30), image OID); 
CREATE TABLE            
janko=# INSERT INTO blobtest1 VALUES ('stackoverflow', lo_import('/tmp/stackoverflow-logo.png')); 
INSERT 0 1 
janko=# SELECT * FROM blobtest1; 
       name    | image 
--------------------------------+------- 
stackoverflow     | 16389 
(1 row) 

una colonna stile OID. getBlob legge i dati dalla colonna e li converte in Long. Quindi tenta di leggere i dati binari associati dalla sua memoria interna.

D'altra parte, con BYTEA è possibile inserire piccoli pezzi di dati binari direttamente nel DB. Per esempio:

janko=# CREATE TABLE blobtest2 (name CHAR(30), image BYTEA); 
CREATE TABLE 
janko=# INSERT INTO blobtest2 VALUES ('somebinary', E'\\336\\255\\276\\357\\336\\255\\276\\357'); 
INSERT 0 1 
janko=# SELECT * FROM blobtest2; 
       name    |    image 
--------------------------------+---------------------------------- 
somebinary      | \336\255\276\357\336\255\276\357 
(1 row) 

Qui, la colonna di dati contiene direttamente i dati binari. Se si tenta di utilizzare getBlob su una colonna di questo tipo, i dati verranno comunque interpretati come OID, ma ovviamente non si adatterà a Long. Proviamolo sul database, abbiamo appena creato:

groovy:000> import java.sql.* 
===> [import java.sql.*] 
groovy:000> Class.forName("org.postgresql.Driver"); 
===> class org.postgresql.Driver 
groovy:000> db = DriverManager.getConnection("jdbc:postgresql:janko", "janko", "qwertz"); 
===> [email protected] 
groovy:000> ps = db.prepareStatement("SELECT image FROM blobtest2 WHERE name = ?"); 
===> SELECT image FROM blobtest2 WHERE name = ? 
groovy:000> ps.setString(1, "somebinary") 
===> null 
groovy:000> rs = ps.executeQuery() 
===> [email protected] 
groovy:000> rs.next() 
===> true 
groovy:000> rs.getBlob("image") 
ERROR org.postgresql.util.PSQLException: Bad value for type long : \336\255\276\357\336\255\276\357 
     at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong (AbstractJdbc2ResultSet.java:2796) 
     at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong (AbstractJdbc2ResultSet.java:2019) 
     at org.postgresql.jdbc4.Jdbc4ResultSet.getBlob (Jdbc4ResultSet.java:52) 
     at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getBlob (AbstractJdbc2ResultSet.java:335) 
     at groovysh_evaluate.run (groovysh_evaluate:3) 
     ... 
+0

Grazie! Quindi rs.getBytes ("immagine") ha funzionato per me per ottenere il byteArray :-) – Bohne

Problemi correlati