java - conexion - Postgresql, JDBC y BLOBs de transmisión
jdbc postgresql 9 (2)
Estoy tratando de recuperar un blob de una base de datos de postgres usando los controladores jdbc. Es demasiado grande para tenerlo en la memoria, así que quiero transmitirlo como descarga. Intenté usar el método getBinaryStream en ResultSet, pero resulta que este método realmente lo lee todo en la memoria, por lo que no funciona para archivos grandes.
Aparentemente, uno puede usar el método getBlob en el conjunto de resultados y presumiblemente obtener el flujo de entrada desde el blob e ir desde allí, pero ahí es donde me encuentro con mi 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")
Ese es el código que estoy ejecutando. Cuando llega a esa última línea, arroja un error que no puedo entender ...
org.postgresql.util.PSQLException: valor incorrecto para el tipo long: xxxxxx
"xxxxxx" entonces es el contenido del archivo. Se puede imaginar que se vuelve bastante largo, pero no es realmente el punto.
Estoy atorado aqui. ¿Alguien tiene alguna idea sobre lo que está pasando? Heck, incluso tomaré métodos alternativos para transmitir grandes blobs como descarga.
¿Ayudarían los documentos de PostgreSQL para "Almacenar datos binarios"?
http://jdbc.postgresql.org/documentation/head/binary-data.html
La sección titulada "Recuperar la imagen del objeto grande", que se encuentra en la parte inferior de la página, puede ayudar.
Mi conjetura es que ha mezclado blobs estilo OID y BYTEA. Los objetos binarios grandes se almacenan indirectamente con columnas OID en Postgres. Postgres almacena los datos reales del archivo en algún lugar fuera de la tabla de la base de datos. La columna solo contiene un identificador de objeto que está asociado internamente con el blob. Por ejemplo:
janko=# CREATE TABLE blobtest1 (name CHAR(30), image OID);
CREATE TABLE
janko=# INSERT INTO blobtest1 VALUES ('''', lo_import(''/tmp/-logo.png''));
INSERT 0 1
janko=# SELECT * FROM blobtest1;
name | image
--------------------------------+-------
| 16389
(1 row)
Si usa el método ResultSet#getBlob(String)
, se espera una columna de estilo OID. getBlob
lee los datos de la columna y los convierte a Long
. Luego intenta leer los datos binarios asociados desde su almacenamiento interno.
Por otro lado, con BYTEA puede colocar pequeños fragmentos de datos binarios directamente en su base de datos. Por ejemplo:
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)
Aquí, la columna de datos contiene directamente los datos binarios. Si intenta utilizar getBlob
en una columna de este tipo, los datos se seguirán interpretando como un OID, pero obviamente no se ajustarán a un Long
. Probemos esto en la base de datos, acabamos de crear:
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");
===> org.postgresql.jdbc4.Jdbc4Connection@3a0b2c64
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()
===> org.postgresql.jdbc4.Jdbc4ResultSet@66f9104a
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)
...